| From 1a1d61a2faf0390033a3766559ce0e758e15894e Mon Sep 17 00:00:00 2001 |
| From: Luka Perkov <openwrt@lukaperkov.net> |
| Date: Wed, 29 Aug 2012 22:08:16 +0200 |
| Subject: net: switchlib: add driver for Atheros AR8216 |
| |
| Signed-off-by: Luka Perkov <openwrt@lukaperkov.net> |
| Signed-off-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com> |
| |
| --- a/drivers/net/switch/Makefile |
| +++ b/drivers/net/switch/Makefile |
| @@ -12,6 +12,7 @@ LIB := $(obj)libswitch.o |
| COBJS-$(CONFIG_SWITCH_MULTI) += switch.o |
| COBJS-$(CONFIG_SWITCH_PSB697X) += psb697x.o |
| COBJS-$(CONFIG_SWITCH_ADM6996I) += adm6996i.o |
| +COBJS-$(CONFIG_SWITCH_AR8216) += ar8216.o |
| |
| COBJS := $(COBJS-y) |
| SRCS := $(COBJS:.o=.c) |
| --- /dev/null |
| +++ b/drivers/net/switch/ar8216.c |
| @@ -0,0 +1,114 @@ |
| +/* |
| + * Copyright (C) 2012 Luka Perkov <luka@openwrt.org> |
| + * |
| + * SPDX-License-Identifier: GPL-2.0+ |
| + */ |
| + |
| +#include <common.h> |
| +#include <malloc.h> |
| +#include <miiphy.h> |
| +#include <switch.h> |
| +#include <netdev.h> |
| + |
| +#define BITS(_s, _n) (((1UL << (_n)) - 1) << _s) |
| + |
| +#define AR8216_REG_CTRL 0x0000 |
| +#define AR8216_CTRL_REVISION BITS(0, 8) |
| +#define AR8216_CTRL_VERSION BITS(8, 8) |
| + |
| +#define AR8216_PROBE_RETRIES 10 |
| + |
| +static void split_addr(u32 regaddr, u16 *r1, u16 *r2, u16 *page) |
| +{ |
| + regaddr >>= 1; |
| + *r1 = regaddr & 0x1e; |
| + |
| + regaddr >>= 5; |
| + *r2 = regaddr & 0x7; |
| + |
| + regaddr >>= 3; |
| + *page = regaddr & 0x1ff; |
| +} |
| + |
| +static int ar8216_mii_read(struct mii_dev *bus, u32 reg) |
| +{ |
| + u16 r1, r2, page; |
| + u16 lo, hi; |
| + |
| + split_addr(reg, &r1, &r2, &page); |
| + |
| + bus->write(bus, 0x18, MDIO_DEVAD_NONE, 0, page); |
| + __udelay(1000); |
| + |
| + lo = bus->read(bus, 0x10 | r2, MDIO_DEVAD_NONE, r1); |
| + hi = bus->read(bus, 0x10 | r2, MDIO_DEVAD_NONE, r1 + 1); |
| + |
| + return (hi << 16) | lo; |
| +} |
| + |
| +static void ar8216_mii_write(struct mii_dev *bus, u16 reg, u32 val) |
| +{ |
| + u16 r1, r2, r3; |
| + u16 lo, hi; |
| + |
| + split_addr((u32) reg, &r1, &r2, &r3); |
| + |
| + bus->write(bus, 0x18, MDIO_DEVAD_NONE, 0, r3); |
| + __udelay(1000); |
| + |
| + lo = val & 0xffff; |
| + hi = (u16) (val >> 16); |
| + bus->write(bus, 0x10 | r2, MDIO_DEVAD_NONE, r1 + 1, hi); |
| + bus->write(bus, 0x10 | r2, MDIO_DEVAD_NONE, r1, lo); |
| +} |
| + |
| +static int ar8216_probe(struct switch_device *dev) |
| +{ |
| + struct mii_dev *bus = dev->bus; |
| + u32 val; |
| + u16 id; |
| + |
| + val = ar8216_mii_read(bus, AR8216_REG_CTRL); |
| + if (val == ~0) |
| + return 1; |
| + |
| + id = val & (AR8216_CTRL_REVISION | AR8216_CTRL_VERSION); |
| + |
| + switch (id) { |
| + case 0x0101: |
| + return 0; |
| + default: |
| + return 1; |
| + } |
| +} |
| + |
| +static void ar8216_setup(struct switch_device *dev) |
| +{ |
| + struct mii_dev *bus = dev->bus; |
| + |
| + ar8216_mii_write(bus, 0x200, 0x200); |
| + ar8216_mii_write(bus, 0x300, 0x200); |
| + ar8216_mii_write(bus, 0x400, 0x200); |
| + ar8216_mii_write(bus, 0x500, 0x200); |
| + ar8216_mii_write(bus, 0x600, 0x7d); |
| + ar8216_mii_write(bus, 0x38, 0xc000050e); |
| + ar8216_mii_write(bus, 0x104, 0x4004); |
| + ar8216_mii_write(bus, 0x60, 0xffffffff); |
| + ar8216_mii_write(bus, 0x64, 0xaaaaaaaa); |
| + ar8216_mii_write(bus, 0x68, 0x55555555); |
| + ar8216_mii_write(bus, 0x6c, 0x0); |
| + ar8216_mii_write(bus, 0x70, 0x41af); |
| +} |
| + |
| +static struct switch_driver ar8216_drv = { |
| + .name = "ar8216", |
| +}; |
| + |
| +void switch_ar8216_init(void) |
| +{ |
| + /* for archs with manual relocation */ |
| + ar8216_drv.probe = ar8216_probe; |
| + ar8216_drv.setup = ar8216_setup; |
| + |
| + switch_driver_register(&ar8216_drv); |
| +} |
| --- a/drivers/net/switch/switch.c |
| +++ b/drivers/net/switch/switch.c |
| @@ -23,6 +23,9 @@ void switch_init(void) |
| #if defined(CONFIG_SWITCH_ADM6996I) |
| switch_adm6996i_init(); |
| #endif |
| +#if defined(CONFIG_SWITCH_AR8216) |
| + switch_ar8216_init(); |
| +#endif |
| |
| board_switch_init(); |
| } |
| --- a/include/switch.h |
| +++ b/include/switch.h |
| @@ -99,6 +99,7 @@ static inline void switch_setup(struct s |
| /* Init functions for supported Switch drivers */ |
| extern void switch_psb697x_init(void); |
| extern void switch_adm6996i_init(void); |
| +extern void switch_ar8216_init(void); |
| |
| #endif /* __SWITCH_H */ |
| |