Commit 67fbaabd authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

dev: driver for AD9520 clock distribution chip

parent f988d95c
/*
* This work is part of the White Rabbit project
*
* Copyright (C) 2019 CERN (www.cern.ch)
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "dev/ad9520.h"
#include "dev/i2c.h"
// Write to AD9510 via I2C
void ad9520_write(struct ad9520_device *dev, uint32_t reg, uint8_t value)
{
// pp_printf("ad9520_write reg %x value %x\n", reg, value);
bb_i2c_start( dev->bus );
bb_i2c_put_byte( dev->bus, dev->addr << 1 );
bb_i2c_put_byte( dev->bus, reg >> 8);
bb_i2c_put_byte( dev->bus, reg & 0xff);
bb_i2c_put_byte( dev->bus, value );
bb_i2c_stop( dev->bus );
}
// Read from AD9510 via I2C
uint8_t ad9520_read(struct ad9520_device *dev, uint32_t reg) {
uint8_t rv;
bb_i2c_start( dev->bus );
int ack = bb_i2c_put_byte( dev->bus, dev->addr << 1 );
bb_i2c_put_byte( dev->bus, reg >> 8);
bb_i2c_put_byte( dev->bus, reg & 0xff);
bb_i2c_repeat_start( dev->bus );
bb_i2c_put_byte( dev->bus, (dev->addr << 1) | 1 );
bb_i2c_get_byte( dev->bus, &rv, 1);
bb_i2c_stop( dev->bus );
return rv;
}
int ad9520_init(struct ad9520_device *dev, struct i2c_bus *bus, uint8_t addr)
{
dev->bus = bus;
dev->addr = addr;
ad9520_write( dev, 0x00, (1<<5) | (1<<2) ); // soft reset
ad9520_write( dev, 0x232, 0x01); // commit
int id = ad9520_read( dev, 0x3 );
pp_printf("Init AD9520: ID = %x\n", id);
return (id == 0x61 ? 0 : -1);
}
int ad9520_configure(struct ad9520_device *dev, struct ad95xx_config *cfg)
{
int i;
for(i = 0; i < cfg->n_regs; i++) {
ad9520_write(dev, cfg->regs[i].addr, cfg->regs[i].value);
}
ad9520_write(dev, 0x232, 0x01); // commit
/*
for(i = 0; i < cfg->n_regs; i++) {
uint32_t r = ad9520_read(dev, cfg->regs[i].addr);
pp_printf("readback %x %x %x\n" , cfg->regs[i].addr , cfg->regs[i].value, r);
}
*/
return 0;
};
int ad9520_enable_output(struct ad9520_device *dev, int channel, int enabled )
{
uint32_t val = enabled ? 0x64 : 0x65; // LVPECL
ad9520_write(dev, 0xf0 + channel, val);
ad9520_write(dev, 0x232, 0x01); // commit
return 0;
}
int ad9520_set_output_divider( struct ad9520_device *dev, int channel, int divider)
{
int index = channel / 3;
if( divider == 1 ) // undivided output
{
ad9520_write(dev, 0x190 + 3*index, 0);
ad9520_write(dev, 0x191 + 3*index, 0x80); // bypass divider, ignore ysnc
ad9520_write(dev, 0x192 + 3*index, 0);
} else {
int cyc = (divider / 2) - 1;
if( cyc >= 8)
return -1;
ad9520_write(dev, 0x190 + 3*index, cyc | (cyc<<4));
ad9520_write(dev, 0x191 + 3*index, 0x00); // enable divider, ignore ysnc
ad9520_write(dev, 0x192 + 3*index, 0);
}
ad9520_write(dev, 0x232, 0x01); // commit
return 0;
}
......@@ -24,7 +24,8 @@ obj-$(CONFIG_EMBEDDED_NODE) += \
dev/spi_flash.o \
dev/clock_monitor.o \
dev/iuart.o \
dev/ltc6950.o
dev/ltc6950.o \
dev/ad9520.o
obj-$(CONFIG_WR_NODE) += \
dev/temperature.o \
......
/*
* This work is part of the White Rabbit project
*
* Copyright (C) 2019 CERN (www.cern.ch)
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __AD9520_H
#define __AD9520_H
#include "board.h"
#include "dev/i2c.h"
#include "dev/ad951x.h"
#define AD9510_BIT_DELAY 100
struct ad9520_device {
struct i2c_bus *bus;
uint8_t addr;
};
void ad9520_write(struct ad9520_device *dev, uint32_t reg, uint8_t value);
uint8_t ad9520_read(struct ad9520_device *dev, uint32_t reg);
void ad9520_soft_reset(struct ad9520_device *dev);
int ad9520_init(struct ad9520_device *dev, struct i2c_bus *bus, uint8_t addr);
int ad9520_configure(struct ad9520_device *dev, struct ad95xx_config *cfg);
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment