int offset; /* index of last configuration register */
u32 mask; /* configuration-value mask bits */
int width; /* configuration register bit width */
+ bool bits_per_mux;
};
struct single_fdt_pin_cfg {
fdt32_t val; /* configuration register value */
};
+struct single_fdt_bits_cfg {
+ fdt32_t reg; /* configuration register offset */
+ fdt32_t val; /* configuration register value */
+ fdt32_t mask; /* configuration register mask */
+};
+
/**
* single_configure_pins() - Configure pins based on FDT data
*
return 0;
}
+static int single_configure_bits(struct udevice *dev,
+ const struct single_fdt_bits_cfg *pins,
+ int size)
+{
+ struct single_pdata *pdata = dev->platdata;
+ int count = size / sizeof(struct single_fdt_bits_cfg);
+ phys_addr_t n, reg;
+ u32 val, mask;
+
+ for (n = 0; n < count; n++, pins++) {
+ reg = fdt32_to_cpu(pins->reg);
+ if ((reg < 0) || (reg > pdata->offset)) {
+ dev_dbg(dev, " invalid register offset 0x%pa\n", ®);
+ continue;
+ }
+ reg += pdata->base;
+
+ mask = fdt32_to_cpu(pins->mask);
+ val = fdt32_to_cpu(pins->val) & mask;
+
+ switch (pdata->width) {
+ case 16:
+ writew((readw(reg) & ~mask) | val, reg);
+ break;
+ case 32:
+ writel((readl(reg) & ~mask) | val, reg);
+ break;
+ default:
+ dev_warn(dev, "unsupported register width %i\n",
+ pdata->width);
+ continue;
+ }
+ dev_dbg(dev, " reg/val 0x%pa/0x%08x\n", ®, val);
+ }
+ return 0;
+}
static int single_set_state(struct udevice *dev,
struct udevice *config)
{
const void *fdt = gd->fdt_blob;
const struct single_fdt_pin_cfg *prop;
+ const struct single_fdt_bits_cfg *prop_bits;
int len;
prop = fdt_getprop(fdt, dev_of_offset(config), "pinctrl-single,pins",
&len);
+
if (prop) {
dev_dbg(dev, "configuring pins for %s\n", config->name);
if (len % sizeof(struct single_fdt_pin_cfg)) {
return -FDT_ERR_BADSTRUCTURE;
}
single_configure_pins(dev, prop, len);
- len = 0;
+ return 0;
}
+ /* pinctrl-single,pins not found so check for pinctrl-single,bits */
+ prop_bits = fdt_getprop(fdt, dev_of_offset(config),
+ "pinctrl-single,bits",
+ &len);
+ if (prop_bits) {
+ dev_dbg(dev, "configuring pins for %s\n", config->name);
+ if (len % sizeof(struct single_fdt_bits_cfg)) {
+ dev_dbg(dev, " invalid bits configuration in fdt\n");
+ return -FDT_ERR_BADSTRUCTURE;
+ }
+ single_configure_bits(dev, prop_bits, len);
+ return 0;
+ }
+
+ /* Neither 'pinctrl-single,pins' nor 'pinctrl-single,bits' were found */
return len;
}
pdata->mask = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
"pinctrl-single,function-mask",
0xffffffff);
+ pdata->bits_per_mux = fdtdec_get_bool(gd->fdt_blob, dev_of_offset(dev),
+ "pinctrl-single,bit-per-mux");
+
return 0;
}