miic
void (*miic_write)(struct miic *miic, int offset, u32 value);
struct miic *miic;
static void miic_unlock_regs(struct miic *miic)
writel(0x00A5, miic->base + MIIC_PRCMD);
writel(0x0001, miic->base + MIIC_PRCMD);
writel(0xFFFE, miic->base + MIIC_PRCMD);
writel(0x0001, miic->base + MIIC_PRCMD);
static void miic_lock_regs(struct miic *miic)
writel(0x0000, miic->base + MIIC_PRCMD);
static void miic_reg_writel_unlocked(struct miic *miic, int offset, u32 value)
writel(value, miic->base + offset);
static void miic_reg_writel_locked(struct miic *miic, int offset, u32 value)
miic_unlock_regs(miic);
writel(value, miic->base + offset);
miic_lock_regs(miic);
static void miic_reg_writel(struct miic *miic, int offset, u32 value)
miic->of_data->miic_write(miic, offset, value);
static u32 miic_reg_readl(struct miic *miic, int offset)
return readl(miic->base + offset);
static void miic_reg_rmw(struct miic *miic, int offset, u32 mask, u32 val)
spin_lock(&miic->lock);
reg = miic_reg_readl(miic, offset);
miic_reg_writel(miic, offset, reg);
spin_unlock(&miic->lock);
static void miic_converter_enable(struct miic *miic, int port, int enable)
miic_reg_rmw(miic, MIIC_CONVRST, MIIC_CONVRST_PHYIF_RST(port), val);
struct miic *miic = miic_port->miic;
miic_reg_rmw(miic, MIIC_CONVCTRL(port), mask, val);
miic_converter_enable(miic, miic_port->port, 1);
struct miic *miic = miic_port->miic;
miic_reg_rmw(miic, MIIC_CONVCTRL(port),
struct miic *miic = miic_port->miic;
miic_reg_rmw(miic, MIIC_CONVCTRL(miic_port->port), mask, val);
miic_converter_enable(miic, miic_port->port, 1);
struct miic *miic;
miic = platform_get_drvdata(pdev);
of_data = miic->of_data;
device_link_add(dev, miic->dev, DL_FLAG_AUTOREMOVE_CONSUMER);
miic_port->miic = miic;
miic_converter_enable(miic_port->miic, miic_port->port, 0);
static int miic_init_hw(struct miic *miic, u32 cfg_mode)
u8 sw_mode_mask = miic->of_data->sw_mode_mask;
if (miic->of_data->init_unlock_lock_regs)
miic_unlock_regs(miic);
miic_reg_writel(miic, MIIC_MODCTRL,
for (port = 0; port < miic->of_data->miic_port_max; port++) {
miic_converter_enable(miic, port, 0);
miic_reg_writel(miic, MIIC_SWCTRL, 0x0);
miic_reg_writel(miic, MIIC_SWDUPC, 0x0);
static void miic_dump_conf(struct miic *miic, s8 *conf)
const struct miic_of_data *of_data = miic->of_data;
dev_err(miic->dev, "%s: %s\n",
static int miic_match_dt_conf(struct miic *miic, s8 *dt_val, u32 *mode_cfg)
const struct miic_of_data *of_data = miic->of_data;
miic->of_data->conf_conv_count)) {
dev_err(miic->dev, "Failed to apply requested configuration\n");
miic_dump_conf(miic, dt_val);
static void miic_configure_phy_link(struct miic *miic, u32 conf,
if (miic->of_data->type == MIIC_TYPE_RZN1) {
miic->link_cfg.mask |= mask;
miic->link_cfg.val |= mask;
miic->link_cfg.val &= ~mask;
static int miic_parse_dt(struct miic *miic, u32 *mode_cfg)
struct device_node *np = miic->dev->of_node;
dt_val = kmalloc_objs(*dt_val, miic->of_data->conf_conv_count);
dt_val[port + !miic->of_data->miic_port_start] = conf;
miic_configure_phy_link(miic, conf, port, active_low);
ret = miic_match_dt_conf(miic, dt_val, mode_cfg);
struct miic *miic = data;
ret = reset_control_bulk_assert(miic->of_data->reset_count, miic->rsts);
dev_err(miic->dev, "failed to assert reset lines\n");
static int miic_reset_control_init(struct miic *miic)
const struct miic_of_data *of_data = miic->of_data;
struct device *dev = miic->dev;
miic->rsts[i].id = of_data->reset_ids[i];
miic->rsts);
ret = reset_control_bulk_deassert(of_data->reset_count, miic->rsts);
miic);
struct miic *miic;
miic = devm_kzalloc(dev, sizeof(*miic), GFP_KERNEL);
if (!miic)
miic->of_data = of_device_get_match_data(dev);
miic->dev = dev;
ret = miic_parse_dt(miic, &mode_cfg);
spin_lock_init(&miic->lock);
miic->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(miic->base))
return PTR_ERR(miic->base);
ret = miic_reset_control_init(miic);
ret = miic_init_hw(miic, mode_cfg);
miic_reg_rmw(miic, MIIC_PHY_LINK, miic->link_cfg.mask, miic->link_cfg.val);
platform_set_drvdata(pdev, miic);