Home | History | Annotate | Download | only in a38x
      1 #include <common.h>
      2 #include <dm.h>
      3 #include <miiphy.h>
      4 #include <asm-generic/gpio.h>
      5 
      6 #include "ihs_phys.h"
      7 #include "dt_helpers.h"
      8 
      9 enum {
     10 	PORTTYPE_MAIN_CAT,
     11 	PORTTYPE_TOP_CAT,
     12 	PORTTYPE_16C_16F,
     13 	PORTTYPE_UNKNOWN
     14 };
     15 
     16 static struct porttype {
     17 	bool phy_invert_in_pol;
     18 	bool phy_invert_out_pol;
     19 } porttypes[] = {
     20 	{ true, false },
     21 	{ false, true },
     22 	{ false, false },
     23 };
     24 
     25 static void ihs_phy_config(struct phy_device *phydev, bool qinpn, bool qoutpn)
     26 {
     27 	u16 reg;
     28 
     29 	phy_config(phydev);
     30 
     31 	/* enable QSGMII autonegotiation with flow control */
     32 	phy_write(phydev, MDIO_DEVAD_NONE, 22, 0x0004);
     33 	reg = phy_read(phydev, MDIO_DEVAD_NONE, 16);
     34 	reg |= (3 << 6);
     35 	phy_write(phydev, MDIO_DEVAD_NONE, 16, reg);
     36 
     37 	/*
     38 	 * invert QSGMII Q_INP/N and Q_OUTP/N if required
     39 	 * and perform global reset
     40 	 */
     41 	reg = phy_read(phydev, MDIO_DEVAD_NONE, 26);
     42 	if (qinpn)
     43 		reg |= (1 << 13);
     44 	if (qoutpn)
     45 		reg |= (1 << 12);
     46 	reg |= (1 << 15);
     47 	phy_write(phydev, MDIO_DEVAD_NONE, 26, reg);
     48 
     49 	/* advertise 1000BASE-T full-duplex only  */
     50 	phy_write(phydev, MDIO_DEVAD_NONE, 22, 0x0000);
     51 	reg = phy_read(phydev, MDIO_DEVAD_NONE, 4);
     52 	reg &= ~0x1e0;
     53 	phy_write(phydev, MDIO_DEVAD_NONE, 4, reg);
     54 	reg = phy_read(phydev, MDIO_DEVAD_NONE, 9);
     55 	reg = (reg & ~0x300) | 0x200;
     56 	phy_write(phydev, MDIO_DEVAD_NONE, 9, reg);
     57 
     58 	/* copper power up */
     59 	reg = phy_read(phydev, MDIO_DEVAD_NONE, 16);
     60 	reg &= ~0x0004;
     61 	phy_write(phydev, MDIO_DEVAD_NONE, 16, reg);
     62 }
     63 
     64 uint calculate_octo_phy_mask(void)
     65 {
     66 	uint k;
     67 	uint octo_phy_mask = 0;
     68 	struct gpio_desc gpio = {};
     69 	char gpio_name[64];
     70 	static const char * const dev_name[] = {"pca9698@23", "pca9698@21",
     71 						"pca9698@24", "pca9698@25",
     72 						"pca9698@26"};
     73 
     74 	/* mark all octo phys that should be present */
     75 	for (k = 0; k < 5; ++k) {
     76 		snprintf(gpio_name, 64, "cat-gpio-%u", k);
     77 
     78 		if (request_gpio_by_name(&gpio, dev_name[k], 0x20, gpio_name))
     79 			continue;
     80 
     81 		/* check CAT flag */
     82 		if (dm_gpio_get_value(&gpio))
     83 			octo_phy_mask |= (1 << (k * 2));
     84 		else
     85 			/* If CAT == 0, there's no second octo phy -> skip */
     86 			continue;
     87 
     88 		snprintf(gpio_name, 64, "second-octo-gpio-%u", k);
     89 
     90 		if (request_gpio_by_name(&gpio, dev_name[k], 0x27, gpio_name)) {
     91 			/* default: second octo phy is present */
     92 			octo_phy_mask |= (1 << (k * 2 + 1));
     93 			continue;
     94 		}
     95 
     96 		if (dm_gpio_get_value(&gpio) == 0)
     97 			octo_phy_mask |= (1 << (k * 2 + 1));
     98 	}
     99 
    100 	return octo_phy_mask;
    101 }
    102 
    103 int register_miiphy_bus(uint k, struct mii_dev **bus)
    104 {
    105 	int retval;
    106 	struct mii_dev *mdiodev = mdio_alloc();
    107 	char *name = bb_miiphy_buses[k].name;
    108 
    109 	if (!mdiodev)
    110 		return -ENOMEM;
    111 	strncpy(mdiodev->name,
    112 		name,
    113 		MDIO_NAME_LEN);
    114 	mdiodev->read = bb_miiphy_read;
    115 	mdiodev->write = bb_miiphy_write;
    116 
    117 	retval = mdio_register(mdiodev);
    118 	if (retval < 0)
    119 		return retval;
    120 	*bus = miiphy_get_dev_by_name(name);
    121 
    122 	return 0;
    123 }
    124 
    125 struct porttype *get_porttype(uint octo_phy_mask, uint k)
    126 {
    127 	uint octo_index = k * 4;
    128 
    129 	if (!k) {
    130 		if (octo_phy_mask & 0x01)
    131 			return &porttypes[PORTTYPE_MAIN_CAT];
    132 		else if (!(octo_phy_mask & 0x03))
    133 			return &porttypes[PORTTYPE_16C_16F];
    134 	} else {
    135 		if (octo_phy_mask & (1 << octo_index))
    136 			return &porttypes[PORTTYPE_TOP_CAT];
    137 	}
    138 
    139 	return NULL;
    140 }
    141 
    142 int init_single_phy(struct porttype *porttype, struct mii_dev *bus,
    143 		    uint bus_idx, uint m, uint phy_idx)
    144 {
    145 	struct phy_device *phydev = phy_find_by_mask(
    146 		bus, 1 << (m * 8 + phy_idx),
    147 		PHY_INTERFACE_MODE_MII);
    148 
    149 	printf(" %u", bus_idx * 32 + m * 8 + phy_idx);
    150 
    151 	if (!phydev)
    152 		puts("!");
    153 	else
    154 		ihs_phy_config(phydev, porttype->phy_invert_in_pol,
    155 			       porttype->phy_invert_out_pol);
    156 
    157 	return 0;
    158 }
    159 
    160 int init_octo_phys(uint octo_phy_mask)
    161 {
    162 	uint bus_idx;
    163 
    164 	/* there are up to four octo-phys on each mdio bus */
    165 	for (bus_idx = 0; bus_idx < bb_miiphy_buses_num; ++bus_idx) {
    166 		uint m;
    167 		uint octo_index = bus_idx * 4;
    168 		struct mii_dev *bus = NULL;
    169 		struct porttype *porttype = NULL;
    170 		int ret;
    171 
    172 		porttype = get_porttype(octo_phy_mask, bus_idx);
    173 
    174 		if (!porttype)
    175 			continue;
    176 
    177 		for (m = 0; m < 4; ++m) {
    178 			uint phy_idx;
    179 
    180 			/**
    181 			 * Register a bus device if there is at least one phy
    182 			 * on the current bus
    183 			 */
    184 			if (!m && octo_phy_mask & (0xf << octo_index)) {
    185 				ret = register_miiphy_bus(bus_idx, &bus);
    186 				if (ret)
    187 					return ret;
    188 			}
    189 
    190 			if (!(octo_phy_mask & BIT(octo_index + m)))
    191 				continue;
    192 
    193 			for (phy_idx = 0; phy_idx < 8; ++phy_idx)
    194 				init_single_phy(porttype, bus, bus_idx, m,
    195 						phy_idx);
    196 		}
    197 	}
    198 
    199 	return 0;
    200 }
    201 
    202 /*
    203  * MII GPIO bitbang implementation
    204  * MDC MDIO bus
    205  * 13  14   PHY1-4
    206  * 25  45   PHY5-8
    207  * 46  24   PHY9-10
    208  */
    209 
    210 struct gpio_mii {
    211 	int index;
    212 	struct gpio_desc mdc_gpio;
    213 	struct gpio_desc mdio_gpio;
    214 	int mdc_num;
    215 	int mdio_num;
    216 	int mdio_value;
    217 } gpio_mii_set[] = {
    218 	{ 0, {}, {}, 13, 14, 1 },
    219 	{ 1, {}, {}, 25, 45, 1 },
    220 	{ 2, {}, {}, 46, 24, 1 },
    221 };
    222 
    223 static int mii_mdio_init(struct bb_miiphy_bus *bus)
    224 {
    225 	struct gpio_mii *gpio_mii = bus->priv;
    226 	char name[32] = {};
    227 	struct udevice *gpio_dev1 = NULL;
    228 	struct udevice *gpio_dev2 = NULL;
    229 
    230 	if (uclass_get_device_by_name(UCLASS_GPIO, "gpio@18100", &gpio_dev1) ||
    231 	    uclass_get_device_by_name(UCLASS_GPIO, "gpio@18140", &gpio_dev2)) {
    232 		printf("Could not get GPIO device.\n");
    233 		return 1;
    234 	}
    235 
    236 	if (gpio_mii->mdc_num > 31) {
    237 		gpio_mii->mdc_gpio.dev = gpio_dev2;
    238 		gpio_mii->mdc_gpio.offset = gpio_mii->mdc_num - 32;
    239 	} else {
    240 		gpio_mii->mdc_gpio.dev = gpio_dev1;
    241 		gpio_mii->mdc_gpio.offset = gpio_mii->mdc_num;
    242 	}
    243 	gpio_mii->mdc_gpio.flags = 0;
    244 	snprintf(name, 32, "bb_miiphy_bus-%d-mdc", gpio_mii->index);
    245 	dm_gpio_request(&gpio_mii->mdc_gpio, name);
    246 
    247 	if (gpio_mii->mdio_num > 31) {
    248 		gpio_mii->mdio_gpio.dev = gpio_dev2;
    249 		gpio_mii->mdio_gpio.offset = gpio_mii->mdio_num - 32;
    250 	} else {
    251 		gpio_mii->mdio_gpio.dev = gpio_dev1;
    252 		gpio_mii->mdio_gpio.offset = gpio_mii->mdio_num;
    253 	}
    254 	gpio_mii->mdio_gpio.flags = 0;
    255 	snprintf(name, 32, "bb_miiphy_bus-%d-mdio", gpio_mii->index);
    256 	dm_gpio_request(&gpio_mii->mdio_gpio, name);
    257 
    258 	dm_gpio_set_dir_flags(&gpio_mii->mdc_gpio, GPIOD_IS_OUT);
    259 	dm_gpio_set_value(&gpio_mii->mdc_gpio, 1);
    260 
    261 	return 0;
    262 }
    263 
    264 static int mii_mdio_active(struct bb_miiphy_bus *bus)
    265 {
    266 	struct gpio_mii *gpio_mii = bus->priv;
    267 
    268 	dm_gpio_set_value(&gpio_mii->mdc_gpio, gpio_mii->mdio_value);
    269 
    270 	return 0;
    271 }
    272 
    273 static int mii_mdio_tristate(struct bb_miiphy_bus *bus)
    274 {
    275 	struct gpio_mii *gpio_mii = bus->priv;
    276 
    277 	dm_gpio_set_dir_flags(&gpio_mii->mdio_gpio, GPIOD_IS_IN);
    278 
    279 	return 0;
    280 }
    281 
    282 static int mii_set_mdio(struct bb_miiphy_bus *bus, int v)
    283 {
    284 	struct gpio_mii *gpio_mii = bus->priv;
    285 
    286 	dm_gpio_set_dir_flags(&gpio_mii->mdio_gpio, GPIOD_IS_OUT);
    287 	dm_gpio_set_value(&gpio_mii->mdio_gpio, v);
    288 	gpio_mii->mdio_value = v;
    289 
    290 	return 0;
    291 }
    292 
    293 static int mii_get_mdio(struct bb_miiphy_bus *bus, int *v)
    294 {
    295 	struct gpio_mii *gpio_mii = bus->priv;
    296 
    297 	dm_gpio_set_dir_flags(&gpio_mii->mdio_gpio, GPIOD_IS_IN);
    298 	*v = (dm_gpio_get_value(&gpio_mii->mdio_gpio));
    299 
    300 	return 0;
    301 }
    302 
    303 static int mii_set_mdc(struct bb_miiphy_bus *bus, int v)
    304 {
    305 	struct gpio_mii *gpio_mii = bus->priv;
    306 
    307 	dm_gpio_set_value(&gpio_mii->mdc_gpio, v);
    308 
    309 	return 0;
    310 }
    311 
    312 static int mii_delay(struct bb_miiphy_bus *bus)
    313 {
    314 	udelay(1);
    315 
    316 	return 0;
    317 }
    318 
    319 struct bb_miiphy_bus bb_miiphy_buses[] = {
    320 	{
    321 		.name = "ihs0",
    322 		.init = mii_mdio_init,
    323 		.mdio_active = mii_mdio_active,
    324 		.mdio_tristate = mii_mdio_tristate,
    325 		.set_mdio = mii_set_mdio,
    326 		.get_mdio = mii_get_mdio,
    327 		.set_mdc = mii_set_mdc,
    328 		.delay = mii_delay,
    329 		.priv = &gpio_mii_set[0],
    330 	},
    331 	{
    332 		.name = "ihs1",
    333 		.init = mii_mdio_init,
    334 		.mdio_active = mii_mdio_active,
    335 		.mdio_tristate = mii_mdio_tristate,
    336 		.set_mdio = mii_set_mdio,
    337 		.get_mdio = mii_get_mdio,
    338 		.set_mdc = mii_set_mdc,
    339 		.delay = mii_delay,
    340 		.priv = &gpio_mii_set[1],
    341 	},
    342 	{
    343 		.name = "ihs2",
    344 		.init = mii_mdio_init,
    345 		.mdio_active = mii_mdio_active,
    346 		.mdio_tristate = mii_mdio_tristate,
    347 		.set_mdio = mii_set_mdio,
    348 		.get_mdio = mii_get_mdio,
    349 		.set_mdc = mii_set_mdc,
    350 		.delay = mii_delay,
    351 		.priv = &gpio_mii_set[2],
    352 	},
    353 };
    354 
    355 int bb_miiphy_buses_num = ARRAY_SIZE(bb_miiphy_buses);
    356