#include "dpll.h"
#include "regs.h"
-/* Chip IDs for zl30731 */
-static const u16 zl30731_ids[] = {
- 0x0E93,
- 0x1E93,
- 0x2E93,
+#define ZL_CHIP_INFO(_id, _nchannels, _flags) \
+ { .id = (_id), .num_channels = (_nchannels), .flags = (_flags) }
+
+static const struct zl3073x_chip_info zl3073x_chip_ids[] = {
+ ZL_CHIP_INFO(0x0E30, 2, ZL3073X_FLAG_REF_PHASE_COMP_32),
+ ZL_CHIP_INFO(0x0E93, 1, ZL3073X_FLAG_REF_PHASE_COMP_32),
+ ZL_CHIP_INFO(0x0E94, 2, ZL3073X_FLAG_REF_PHASE_COMP_32),
+ ZL_CHIP_INFO(0x0E95, 3, ZL3073X_FLAG_REF_PHASE_COMP_32),
+ ZL_CHIP_INFO(0x0E96, 4, ZL3073X_FLAG_REF_PHASE_COMP_32),
+ ZL_CHIP_INFO(0x0E97, 5, ZL3073X_FLAG_REF_PHASE_COMP_32),
+ ZL_CHIP_INFO(0x1E93, 1, 0),
+ ZL_CHIP_INFO(0x1E94, 2, 0),
+ ZL_CHIP_INFO(0x1E95, 3, 0),
+ ZL_CHIP_INFO(0x1E96, 4, 0),
+ ZL_CHIP_INFO(0x1E97, 5, 0),
+ ZL_CHIP_INFO(0x1F60, 2, ZL3073X_FLAG_REF_PHASE_COMP_32),
+ ZL_CHIP_INFO(0x2E93, 1, 0),
+ ZL_CHIP_INFO(0x2E94, 2, 0),
+ ZL_CHIP_INFO(0x2E95, 3, 0),
+ ZL_CHIP_INFO(0x2E96, 4, 0),
+ ZL_CHIP_INFO(0x2E97, 5, 0),
+ ZL_CHIP_INFO(0x3FC4, 2, 0),
};
-const struct zl3073x_chip_info zl30731_chip_info = {
- .ids = zl30731_ids,
- .num_ids = ARRAY_SIZE(zl30731_ids),
- .num_channels = 1,
-};
-EXPORT_SYMBOL_NS_GPL(zl30731_chip_info, "ZL3073X");
-
-/* Chip IDs for zl30732 */
-static const u16 zl30732_ids[] = {
- 0x0E30,
- 0x0E94,
- 0x1E94,
- 0x1F60,
- 0x2E94,
- 0x3FC4,
-};
-
-const struct zl3073x_chip_info zl30732_chip_info = {
- .ids = zl30732_ids,
- .num_ids = ARRAY_SIZE(zl30732_ids),
- .num_channels = 2,
-};
-EXPORT_SYMBOL_NS_GPL(zl30732_chip_info, "ZL3073X");
-
-/* Chip IDs for zl30733 */
-static const u16 zl30733_ids[] = {
- 0x0E95,
- 0x1E95,
- 0x2E95,
-};
-
-const struct zl3073x_chip_info zl30733_chip_info = {
- .ids = zl30733_ids,
- .num_ids = ARRAY_SIZE(zl30733_ids),
- .num_channels = 3,
-};
-EXPORT_SYMBOL_NS_GPL(zl30733_chip_info, "ZL3073X");
-
-/* Chip IDs for zl30734 */
-static const u16 zl30734_ids[] = {
- 0x0E96,
- 0x1E96,
- 0x2E96,
-};
-
-const struct zl3073x_chip_info zl30734_chip_info = {
- .ids = zl30734_ids,
- .num_ids = ARRAY_SIZE(zl30734_ids),
- .num_channels = 4,
-};
-EXPORT_SYMBOL_NS_GPL(zl30734_chip_info, "ZL3073X");
-
-/* Chip IDs for zl30735 */
-static const u16 zl30735_ids[] = {
- 0x0E97,
- 0x1E97,
- 0x2E97,
-};
-
-const struct zl3073x_chip_info zl30735_chip_info = {
- .ids = zl30735_ids,
- .num_ids = ARRAY_SIZE(zl30735_ids),
- .num_channels = 5,
-};
-EXPORT_SYMBOL_NS_GPL(zl30735_chip_info, "ZL3073X");
-
#define ZL_RANGE_OFFSET 0x80
#define ZL_PAGE_SIZE 0x80
#define ZL_NUM_PAGES 256
}
static int
-zl3073x_devm_dpll_init(struct zl3073x_dev *zldev, u8 num_dplls)
+zl3073x_devm_dpll_init(struct zl3073x_dev *zldev)
{
struct kthread_worker *kworker;
struct zl3073x_dpll *zldpll;
INIT_LIST_HEAD(&zldev->dplls);
/* Allocate all DPLLs */
- for (i = 0; i < num_dplls; i++) {
+ for (i = 0; i < zldev->info->num_channels; i++) {
zldpll = zl3073x_dpll_alloc(zldev, i);
if (IS_ERR(zldpll)) {
dev_err_probe(zldev->dev, PTR_ERR(zldpll),
/**
* zl3073x_dev_probe - initialize zl3073x device
* @zldev: pointer to zl3073x device
- * @chip_info: chip info based on compatible
*
* Common initialization of zl3073x device structure.
*
* Returns: 0 on success, <0 on error
*/
-int zl3073x_dev_probe(struct zl3073x_dev *zldev,
- const struct zl3073x_chip_info *chip_info)
+int zl3073x_dev_probe(struct zl3073x_dev *zldev)
{
u16 id, revision, fw_ver;
unsigned int i;
if (rc)
return rc;
- /* Check it matches */
- for (i = 0; i < chip_info->num_ids; i++) {
- if (id == chip_info->ids[i])
+ /* Detect chip variant */
+ for (i = 0; i < ARRAY_SIZE(zl3073x_chip_ids); i++) {
+ if (zl3073x_chip_ids[i].id == id)
break;
}
- if (i == chip_info->num_ids) {
+ if (i == ARRAY_SIZE(zl3073x_chip_ids))
return dev_err_probe(zldev->dev, -ENODEV,
- "Unknown or non-match chip ID: 0x%0x\n",
- id);
- }
- zldev->chip_id = id;
+ "Unknown chip ID: 0x%04x\n", id);
+
+ zldev->info = &zl3073x_chip_ids[i];
/* Read revision, firmware version and custom config version */
rc = zl3073x_read_u16(zldev, ZL_REG_REVISION, &revision);
"Failed to initialize mutex\n");
/* Register DPLL channels */
- rc = zl3073x_devm_dpll_init(zldev, chip_info->num_channels);
+ rc = zl3073x_devm_dpll_init(zldev);
if (rc)
return rc;
#define ZL3073X_NUM_PINS (ZL3073X_NUM_INPUT_PINS + \
ZL3073X_NUM_OUTPUT_PINS)
+enum zl3073x_flags {
+ ZL3073X_FLAG_REF_PHASE_COMP_32_BIT,
+ ZL3073X_FLAGS_NBITS /* must be last */
+};
+
+#define __ZL3073X_FLAG(name) BIT(ZL3073X_FLAG_ ## name ## _BIT)
+#define ZL3073X_FLAG_REF_PHASE_COMP_32 __ZL3073X_FLAG(REF_PHASE_COMP_32)
+
+/**
+ * struct zl3073x_chip_info - chip variant identification
+ * @id: chip ID
+ * @num_channels: number of DPLL channels supported by this variant
+ * @flags: chip variant flags
+ */
+struct zl3073x_chip_info {
+ u16 id;
+ u8 num_channels;
+ unsigned long flags;
+};
+
/**
* struct zl3073x_dev - zl3073x device
* @dev: pointer to device
* @regmap: regmap to access device registers
+ * @info: detected chip info
* @multiop_lock: to serialize multiple register operations
- * @chip_id: chip ID read from hardware
* @ref: array of input references' invariants
* @out: array of outs' invariants
* @synth: array of synths' invariants
* @phase_avg_factor: phase offset measurement averaging factor
*/
struct zl3073x_dev {
- struct device *dev;
- struct regmap *regmap;
- struct mutex multiop_lock;
- u16 chip_id;
+ struct device *dev;
+ struct regmap *regmap;
+ const struct zl3073x_chip_info *info;
+ struct mutex multiop_lock;
/* Invariants */
struct zl3073x_ref ref[ZL3073X_NUM_REFS];
u8 phase_avg_factor;
};
-struct zl3073x_chip_info {
- const u16 *ids;
- size_t num_ids;
- int num_channels;
-};
-
-extern const struct zl3073x_chip_info zl30731_chip_info;
-extern const struct zl3073x_chip_info zl30732_chip_info;
-extern const struct zl3073x_chip_info zl30733_chip_info;
-extern const struct zl3073x_chip_info zl30734_chip_info;
-extern const struct zl3073x_chip_info zl30735_chip_info;
extern const struct regmap_config zl3073x_regmap_config;
struct zl3073x_dev *zl3073x_devm_alloc(struct device *dev);
-int zl3073x_dev_probe(struct zl3073x_dev *zldev,
- const struct zl3073x_chip_info *chip_info);
+int zl3073x_dev_probe(struct zl3073x_dev *zldev);
int zl3073x_dev_start(struct zl3073x_dev *zldev, bool full);
void zl3073x_dev_stop(struct zl3073x_dev *zldev);
static inline bool
zl3073x_dev_is_ref_phase_comp_32bit(struct zl3073x_dev *zldev)
{
- switch (zldev->chip_id) {
- case 0x0E30:
- case 0x0E93:
- case 0x0E94:
- case 0x0E95:
- case 0x0E96:
- case 0x0E97:
- case 0x1F60:
- return true;
- default:
- return false;
- }
+ return zldev->info->flags & ZL3073X_FLAG_REF_PHASE_COMP_32;
}
static inline bool
return dev_err_probe(dev, PTR_ERR(zldev->regmap),
"Failed to initialize regmap\n");
- return zl3073x_dev_probe(zldev, i2c_get_match_data(client));
+ return zl3073x_dev_probe(zldev);
}
static const struct i2c_device_id zl3073x_i2c_id[] = {
- {
- .name = "zl30731",
- .driver_data = (kernel_ulong_t)&zl30731_chip_info,
- },
- {
- .name = "zl30732",
- .driver_data = (kernel_ulong_t)&zl30732_chip_info,
- },
- {
- .name = "zl30733",
- .driver_data = (kernel_ulong_t)&zl30733_chip_info,
- },
- {
- .name = "zl30734",
- .driver_data = (kernel_ulong_t)&zl30734_chip_info,
- },
- {
- .name = "zl30735",
- .driver_data = (kernel_ulong_t)&zl30735_chip_info,
- },
+ { "zl30731" },
+ { "zl30732" },
+ { "zl30733" },
+ { "zl30734" },
+ { "zl30735" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, zl3073x_i2c_id);
static const struct of_device_id zl3073x_i2c_of_match[] = {
- { .compatible = "microchip,zl30731", .data = &zl30731_chip_info },
- { .compatible = "microchip,zl30732", .data = &zl30732_chip_info },
- { .compatible = "microchip,zl30733", .data = &zl30733_chip_info },
- { .compatible = "microchip,zl30734", .data = &zl30734_chip_info },
- { .compatible = "microchip,zl30735", .data = &zl30735_chip_info },
+ { .compatible = "microchip,zl30731" },
+ { .compatible = "microchip,zl30732" },
+ { .compatible = "microchip,zl30733" },
+ { .compatible = "microchip,zl30734" },
+ { .compatible = "microchip,zl30735" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, zl3073x_i2c_of_match);
return dev_err_probe(dev, PTR_ERR(zldev->regmap),
"Failed to initialize regmap\n");
- return zl3073x_dev_probe(zldev, spi_get_device_match_data(spi));
+ return zl3073x_dev_probe(zldev);
}
static const struct spi_device_id zl3073x_spi_id[] = {
- {
- .name = "zl30731",
- .driver_data = (kernel_ulong_t)&zl30731_chip_info
- },
- {
- .name = "zl30732",
- .driver_data = (kernel_ulong_t)&zl30732_chip_info,
- },
- {
- .name = "zl30733",
- .driver_data = (kernel_ulong_t)&zl30733_chip_info,
- },
- {
- .name = "zl30734",
- .driver_data = (kernel_ulong_t)&zl30734_chip_info,
- },
- {
- .name = "zl30735",
- .driver_data = (kernel_ulong_t)&zl30735_chip_info,
- },
+ { "zl30731" },
+ { "zl30732" },
+ { "zl30733" },
+ { "zl30734" },
+ { "zl30735" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(spi, zl3073x_spi_id);
static const struct of_device_id zl3073x_spi_of_match[] = {
- { .compatible = "microchip,zl30731", .data = &zl30731_chip_info },
- { .compatible = "microchip,zl30732", .data = &zl30732_chip_info },
- { .compatible = "microchip,zl30733", .data = &zl30733_chip_info },
- { .compatible = "microchip,zl30734", .data = &zl30734_chip_info },
- { .compatible = "microchip,zl30735", .data = &zl30735_chip_info },
+ { .compatible = "microchip,zl30731" },
+ { .compatible = "microchip,zl30732" },
+ { .compatible = "microchip,zl30733" },
+ { .compatible = "microchip,zl30734" },
+ { .compatible = "microchip,zl30735" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, zl3073x_spi_of_match);