Date:2009-08-23 14:00:58 (3 years 9 months ago)
Author:mirko
Commit:b05391b8aa7868c7d983e81e1b55e1d569f1661c
Message:also take over the files for 2.6.31

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@17356 3c298f89-4303-0410-b956-a3cf2f4a3e73
Files: target/linux/generic-2.6/files-2.6.31/drivers/char/gpio_dev.c (1 diff)
target/linux/generic-2.6/files-2.6.31/drivers/input/misc/gpio_buttons.c (1 diff)
target/linux/generic-2.6/files-2.6.31/drivers/leds/leds-alix.c (1 diff)
target/linux/generic-2.6/files-2.6.31/drivers/leds/ledtrig-morse.c (1 diff)
target/linux/generic-2.6/files-2.6.31/drivers/leds/ledtrig-netdev.c (1 diff)
target/linux/generic-2.6/files-2.6.31/drivers/net/phy/ar8216.c (1 diff)
target/linux/generic-2.6/files-2.6.31/drivers/net/phy/mvswitch.c (1 diff)
target/linux/generic-2.6/files-2.6.31/include/linux/glamo-engine.h (1 diff)
target/linux/generic-2.6/files-2.6.31/include/linux/glamofb.h (1 diff)
target/linux/generic-2.6/files-2.6.31/include/linux/gpio_buttons.h (1 diff)
target/linux/generic-2.6/files-2.6.31/include/linux/gpio_dev.h (1 diff)

Change Details

target/linux/generic-2.6/files-2.6.31/drivers/char/gpio_dev.c
1/*
2 * character device wrapper for generic gpio layer
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
17 *
18 * Feedback, Bugs... blogic@openwrt.org
19 *
20 */
21
22#include <linux/module.h>
23#include <linux/errno.h>
24#include <linux/init.h>
25#include <asm/uaccess.h>
26#include <asm/io.h>
27#include <asm/gpio.h>
28#include <asm/atomic.h>
29#include <linux/init.h>
30#include <linux/genhd.h>
31#include <linux/device.h>
32#include <linux/platform_device.h>
33#include <linux/gpio_dev.h>
34
35#define DRVNAME "gpiodev"
36#define DEVNAME "gpio"
37
38static int dev_major;
39static unsigned int gpio_access_mask;
40static struct class *gpiodev_class;
41
42/* Counter is 1, if the device is not opened and zero (or less) if opened. */
43static atomic_t gpio_open_cnt = ATOMIC_INIT(1);
44
45static int
46gpio_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg)
47{
48    int retval = 0;
49
50    if (((1 << arg) & gpio_access_mask) != (1 << arg))
51    {
52        retval = -EINVAL;
53        goto out;
54    }
55
56    switch (cmd)
57    {
58    case GPIO_GET:
59        retval = gpio_get_value(arg);
60        break;
61
62    case GPIO_SET:
63        gpio_set_value(arg, 1);
64        break;
65
66    case GPIO_CLEAR:
67        gpio_set_value(arg, 0);
68        break;
69
70    case GPIO_DIR_IN:
71        gpio_direction_input(arg);
72        break;
73
74    case GPIO_DIR_OUT:
75        gpio_direction_output(arg, 0);
76        break;
77
78    default:
79        retval = -EINVAL;
80        break;
81    }
82
83out:
84    return retval;
85}
86
87static int
88gpio_open(struct inode *inode, struct file *file)
89{
90    int result = 0;
91    unsigned int dev_minor = MINOR(inode->i_rdev);
92
93    if (dev_minor != 0)
94    {
95        printk(KERN_ERR DRVNAME ": trying to access unknown minor device -> %d\n", dev_minor);
96        result = -ENODEV;
97        goto out;
98    }
99
100    /* FIXME: We should really allow multiple applications to open the device
101     * at the same time, as long as the apps access different IO pins.
102     * The generic gpio-registration functions can be used for that.
103     * Two new IOCTLs have to be introduced for that. Need to check userspace
104     * compatibility first. --mb */
105    if (!atomic_dec_and_test(&gpio_open_cnt)) {
106        atomic_inc(&gpio_open_cnt);
107        printk(KERN_ERR DRVNAME ": Device with minor ID %d already in use\n", dev_minor);
108        result = -EBUSY;
109        goto out;
110    }
111
112out:
113    return result;
114}
115
116static int
117gpio_close(struct inode * inode, struct file * file)
118{
119    smp_mb__before_atomic_inc();
120    atomic_inc(&gpio_open_cnt);
121
122    return 0;
123}
124
125struct file_operations gpio_fops = {
126    ioctl: gpio_ioctl,
127    open: gpio_open,
128    release: gpio_close
129};
130
131static int
132gpio_probe(struct platform_device *dev)
133{
134    int result = 0;
135
136    dev_major = register_chrdev(0, DEVNAME, &gpio_fops);
137    if (!dev_major)
138    {
139        printk(KERN_ERR DRVNAME ": Error whilst opening %s \n", DEVNAME);
140        result = -ENODEV;
141        goto out;
142    }
143
144    gpiodev_class = class_create(THIS_MODULE, DRVNAME);
145    device_create(gpiodev_class, NULL, MKDEV(dev_major, 0), dev, DEVNAME);
146
147    printk(KERN_INFO DRVNAME ": gpio device registered with major %d\n", dev_major);
148
149    if (dev->num_resources != 1)
150    {
151        printk(KERN_ERR DRVNAME ": device may only have 1 resource\n");
152        result = -ENODEV;
153        goto out;
154    }
155
156    gpio_access_mask = dev->resource[0].start;
157
158    printk(KERN_INFO DRVNAME ": gpio platform device registered with access mask %08X\n", gpio_access_mask);
159out:
160    return result;
161}
162
163static int
164gpio_remove(struct platform_device *dev)
165{
166    unregister_chrdev(dev_major, DEVNAME);
167    return 0;
168}
169
170static struct
171platform_driver gpio_driver = {
172    .probe = gpio_probe,
173    .remove = gpio_remove,
174    .driver = {
175        .name = "GPIODEV",
176        .owner = THIS_MODULE,
177    },
178};
179
180static int __init
181gpio_mod_init(void)
182{
183    int ret = platform_driver_register(&gpio_driver);
184    if (ret)
185        printk(KERN_INFO DRVNAME ": Error registering platfom driver!");
186
187    return ret;
188}
189
190static void __exit
191gpio_mod_exit(void)
192{
193    platform_driver_unregister(&gpio_driver);
194}
195
196module_init (gpio_mod_init);
197module_exit (gpio_mod_exit);
198
199MODULE_LICENSE("GPL");
200MODULE_AUTHOR("John Crispin / OpenWrt");
201MODULE_DESCRIPTION("Character device for for generic gpio api");
target/linux/generic-2.6/files-2.6.31/drivers/input/misc/gpio_buttons.c
1/*
2 * Driver for buttons on GPIO lines not capable of generating interrupts
3 *
4 * Copyright (C) 2007,2008 Gabor Juhos <juhosg at openwrt.org>
5 *
6 * This file was based on: /drivers/input/misc/cobalt_btns.c
7 * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
8 *
9 * also was based on: /drivers/input/keyboard/gpio_keys.c
10 * Copyright 2005 Phil Blundell
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 *
16 */
17
18#include <linux/kernel.h>
19#include <linux/module.h>
20#include <linux/init.h>
21
22#include <linux/input.h>
23#include <linux/input-polldev.h>
24#include <linux/ioport.h>
25#include <linux/platform_device.h>
26
27#include <linux/gpio_buttons.h>
28
29#include <asm/gpio.h>
30
31#define DRV_NAME "gpio-buttons"
32#define DRV_VERSION "0.1.1"
33#define PFX DRV_NAME ": "
34
35struct gpio_buttons_dev {
36    struct input_polled_dev *poll_dev;
37    struct gpio_buttons_platform_data *pdata;
38};
39
40static void gpio_buttons_poll(struct input_polled_dev *dev)
41{
42    struct gpio_buttons_dev *bdev = dev->private;
43    struct gpio_buttons_platform_data *pdata = bdev->pdata;
44    struct input_dev *input = dev->input;
45    int i;
46
47    for (i = 0; i < bdev->pdata->nbuttons; i++) {
48        struct gpio_button *button = &pdata->buttons[i];
49        unsigned int type = button->type ?: EV_KEY;
50        int state;
51
52        state = gpio_get_value(button->gpio) ? 1 : 0;
53        state ^= button->active_low;
54
55        if (state) {
56            button->count++;
57        } else {
58            if (button->count >= button->threshold) {
59                input_event(input, type, button->code, 1);
60                input_sync(input);
61            }
62            button->count = 0;
63        }
64
65        if (button->count == button->threshold) {
66            input_event(input, type, button->code, 0);
67            input_sync(input);
68        }
69    }
70}
71
72static int __devinit gpio_buttons_probe(struct platform_device *pdev)
73{
74    struct gpio_buttons_platform_data *pdata = pdev->dev.platform_data;
75    struct gpio_buttons_dev *bdev;
76    struct input_polled_dev *poll_dev;
77    struct input_dev *input;
78    int error, i;
79
80
81    if (!pdata)
82        return -ENXIO;
83
84    bdev = kzalloc(sizeof(*bdev), GFP_KERNEL);
85    if (!bdev) {
86        printk(KERN_ERR DRV_NAME "no memory for device\n");
87        return -ENOMEM;
88    }
89
90    poll_dev = input_allocate_polled_device();
91    if (!poll_dev) {
92        printk(KERN_ERR DRV_NAME "no memory for polled device\n");
93        error = -ENOMEM;
94        goto err_free_bdev;
95    }
96
97    poll_dev->private = bdev;
98    poll_dev->poll = gpio_buttons_poll;
99    poll_dev->poll_interval = pdata->poll_interval;
100
101    input = poll_dev->input;
102
103    input->evbit[0] = BIT(EV_KEY);
104    input->name = pdev->name;
105    input->phys = "gpio-buttons/input0";
106    input->dev.parent = &pdev->dev;
107
108    input->id.bustype = BUS_HOST;
109    input->id.vendor = 0x0001;
110    input->id.product = 0x0001;
111    input->id.version = 0x0100;
112
113    for (i = 0; i < pdata->nbuttons; i++) {
114        struct gpio_button *button = &pdata->buttons[i];
115        unsigned int gpio = button->gpio;
116        unsigned int type = button->type ?: EV_KEY;
117
118        error = gpio_request(gpio, button->desc ?
119                button->desc : DRV_NAME);
120        if (error) {
121            printk(KERN_ERR PFX "unable to claim gpio %u, "
122                "error %d\n", gpio, error);
123            goto err_free_gpio;
124        }
125
126        error = gpio_direction_input(gpio);
127        if (error) {
128            printk(KERN_ERR PFX "unable to set direction on "
129                "gpio %u, error %d\n", gpio, error);
130            goto err_free_gpio;
131        }
132
133        input_set_capability(input, type, button->code);
134        button->count = 0;
135    }
136
137    bdev->poll_dev = poll_dev;
138    bdev->pdata = pdata;
139    platform_set_drvdata(pdev, bdev);
140
141    error = input_register_polled_device(poll_dev);
142    if (error) {
143        printk(KERN_ERR PFX "unable to register polled device, "
144            "error %d\n", error);
145        goto err_free_gpio;
146    }
147
148    return 0;
149
150err_free_gpio:
151    for (i = i - 1; i >= 0; i--)
152        gpio_free(pdata->buttons[i].gpio);
153
154    input_free_polled_device(poll_dev);
155
156err_free_bdev:
157    kfree(bdev);
158
159    platform_set_drvdata(pdev, NULL);
160    return error;
161}
162
163static int __devexit gpio_buttons_remove(struct platform_device *pdev)
164{
165    struct gpio_buttons_dev *bdev = platform_get_drvdata(pdev);
166    struct gpio_buttons_platform_data *pdata = bdev->pdata;
167    int i;
168
169    input_unregister_polled_device(bdev->poll_dev);
170
171    for (i = 0; i < pdata->nbuttons; i++)
172        gpio_free(pdata->buttons[i].gpio);
173
174    input_free_polled_device(bdev->poll_dev);
175
176    kfree(bdev);
177    platform_set_drvdata(pdev, NULL);
178
179    return 0;
180}
181
182static struct platform_driver gpio_buttons_driver = {
183    .probe = gpio_buttons_probe,
184    .remove = __devexit_p(gpio_buttons_remove),
185    .driver = {
186        .name = DRV_NAME,
187        .owner = THIS_MODULE,
188    },
189};
190
191static int __init gpio_buttons_init(void)
192{
193    printk(KERN_INFO DRV_NAME " driver version " DRV_VERSION "\n");
194    return platform_driver_register(&gpio_buttons_driver);
195}
196
197static void __exit gpio_buttons_exit(void)
198{
199    platform_driver_unregister(&gpio_buttons_driver);
200}
201
202module_init(gpio_buttons_init);
203module_exit(gpio_buttons_exit);
204
205MODULE_LICENSE("GPL");
206MODULE_AUTHOR("Gabor Juhos <juhosg at openwrt.org>");
207MODULE_VERSION(DRV_VERSION);
208MODULE_DESCRIPTION("Polled buttons driver for CPU GPIOs");
209
target/linux/generic-2.6/files-2.6.31/drivers/leds/leds-alix.c
1/*
2 * LEDs driver for PCEngines ALIX 2/3 series
3 *
4 * Copyright (C) 2007 Petr Liebman
5 *
6 * Based on leds-wrap.c
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/platform_device.h>
16#include <linux/leds.h>
17#include <linux/err.h>
18#include <asm/io.h>
19
20#define DRVNAME "alix-led"
21
22#define ALIX_LED1_PORT (0x6100)
23#define ALIX_LED1_ON (1<<22)
24#define ALIX_LED1_OFF (1<<6)
25
26#define ALIX_LED2_PORT (0x6180)
27#define ALIX_LED2_ON (1<<25)
28#define ALIX_LED2_OFF (1<<9)
29
30#define ALIX_LED3_PORT (0x6180)
31#define ALIX_LED3_ON (1<<27)
32#define ALIX_LED3_OFF (1<<11)
33
34
35static struct platform_device *pdev;
36
37static void alix_led_set_1(struct led_classdev *led_cdev,
38        enum led_brightness value)
39{
40    if (value)
41        outl(ALIX_LED1_ON, ALIX_LED1_PORT);
42    else
43        outl(ALIX_LED1_OFF, ALIX_LED1_PORT);
44}
45
46static void alix_led_set_2(struct led_classdev *led_cdev,
47        enum led_brightness value)
48{
49    if (value)
50        outl(ALIX_LED2_ON, ALIX_LED2_PORT);
51    else
52        outl(ALIX_LED2_OFF, ALIX_LED2_PORT);
53}
54
55static void alix_led_set_3(struct led_classdev *led_cdev,
56        enum led_brightness value)
57{
58    if (value)
59        outl(ALIX_LED3_ON, ALIX_LED3_PORT);
60    else
61        outl(ALIX_LED3_OFF, ALIX_LED3_PORT);
62}
63
64static struct led_classdev alix_led_1 = {
65    .name = "alix:1",
66    .brightness_set = alix_led_set_1,
67};
68
69static struct led_classdev alix_led_2 = {
70    .name = "alix:2",
71    .brightness_set = alix_led_set_2,
72};
73
74static struct led_classdev alix_led_3 = {
75    .name = "alix:3",
76    .brightness_set = alix_led_set_3,
77};
78
79
80#ifdef CONFIG_PM
81static int alix_led_suspend(struct platform_device *dev,
82        pm_message_t state)
83{
84    led_classdev_suspend(&alix_led_1);
85    led_classdev_suspend(&alix_led_2);
86    led_classdev_suspend(&alix_led_3);
87    return 0;
88}
89
90static int alix_led_resume(struct platform_device *dev)
91{
92    led_classdev_resume(&alix_led_1);
93    led_classdev_resume(&alix_led_2);
94    led_classdev_resume(&alix_led_3);
95    return 0;
96}
97#else
98#define alix_led_suspend NULL
99#define alix_led_resume NULL
100#endif
101
102static int alix_led_probe(struct platform_device *pdev)
103{
104    int ret;
105
106    ret = led_classdev_register(&pdev->dev, &alix_led_1);
107    if (ret >= 0)
108    {
109        ret = led_classdev_register(&pdev->dev, &alix_led_2);
110        if (ret >= 0)
111        {
112            ret = led_classdev_register(&pdev->dev, &alix_led_3);
113            if (ret < 0)
114                led_classdev_unregister(&alix_led_2);
115        }
116        if (ret < 0)
117            led_classdev_unregister(&alix_led_1);
118    }
119    return ret;
120}
121
122static int alix_led_remove(struct platform_device *pdev)
123{
124    led_classdev_unregister(&alix_led_1);
125    led_classdev_unregister(&alix_led_2);
126    led_classdev_unregister(&alix_led_3);
127    return 0;
128}
129
130static struct platform_driver alix_led_driver = {
131    .probe = alix_led_probe,
132    .remove = alix_led_remove,
133    .suspend = alix_led_suspend,
134    .resume = alix_led_resume,
135    .driver = {
136        .name = DRVNAME,
137        .owner = THIS_MODULE,
138    },
139};
140
141static int __init alix_led_init(void)
142{
143    int ret;
144
145    ret = platform_driver_register(&alix_led_driver);
146    if (ret < 0)
147        goto out;
148
149    pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0);
150    if (IS_ERR(pdev)) {
151        ret = PTR_ERR(pdev);
152        platform_driver_unregister(&alix_led_driver);
153        goto out;
154    }
155
156out:
157    return ret;
158}
159
160static void __exit alix_led_exit(void)
161{
162    platform_device_unregister(pdev);
163    platform_driver_unregister(&alix_led_driver);
164}
165
166module_init(alix_led_init);
167module_exit(alix_led_exit);
168
169MODULE_AUTHOR("Petr Liebman");
170MODULE_DESCRIPTION("PCEngines ALIX LED driver");
171MODULE_LICENSE("GPL");
172
target/linux/generic-2.6/files-2.6.31/drivers/leds/ledtrig-morse.c
1/*
2 * LED Morse Trigger
3 *
4 * Copyright (C) 2007 Gabor Juhos <juhosg at openwrt.org>
5 *
6 * This file was based on: drivers/led/ledtrig-timer.c
7 * Copyright 2005-2006 Openedhand Ltd.
8 * Author: Richard Purdie <rpurdie@openedhand.com>
9 *
10 * also based on the patch '[PATCH] 2.5.59 morse code panics' posted
11 * in the LKML by Tomas Szepe at Thu, 30 Jan 2003
12 * Copyright (C) 2002 Andrew Rodland <arodland@noln.com>
13 * Copyright (C) 2003 Tomas Szepe <szepe@pinerecords.com>
14 *
15 * This program is free software; you can redistribute it and/or modify it
16 * under the terms of the GNU General Public License version 2 as published
17 * by the Free Software Foundation.
18 *
19 */
20
21#include <linux/kernel.h>
22#include <linux/version.h>
23#include <linux/module.h>
24#include <linux/jiffies.h>
25#include <linux/init.h>
26#include <linux/list.h>
27#include <linux/spinlock.h>
28#include <linux/device.h>
29#include <linux/sysdev.h>
30#include <linux/timer.h>
31#include <linux/ctype.h>
32#include <linux/leds.h>
33
34#include "leds.h"
35
36#define MORSE_DELAY_BASE (HZ/2)
37
38#define MORSE_STATE_BLINK_START 0
39#define MORSE_STATE_BLINK_STOP 1
40
41#define MORSE_DIT_LEN 1
42#define MORSE_DAH_LEN 3
43#define MORSE_SPACE_LEN 7
44
45struct morse_trig_data {
46    unsigned long delay;
47    char *msg;
48
49    unsigned char morse;
50    unsigned char state;
51    char *msgpos;
52    struct timer_list timer;
53};
54
55const unsigned char morsetable[] = {
56    0122, 0, 0310, 0, 0, 0163, /* "#$%&' */
57    055, 0155, 0, 0, 0163, 0141, 0152, 0051, /* ()*+,-./ */
58    077, 076, 074, 070, 060, 040, 041, 043, 047, 057, /* 0-9 */
59    0107, 0125, 0, 0061, 0, 0114, 0, /* :;<=>?@ */
60    006, 021, 025, 011, 002, 024, 013, 020, 004, /* A-I */
61    036, 015, 022, 007, 005, 017, 026, 033, 012, /* J-R */
62    010, 003, 014, 030, 016, 031, 035, 023, /* S-Z */
63    0, 0, 0, 0, 0154 /* [\]^_ */
64};
65
66static inline unsigned char tomorse(char c) {
67    if (c >= 'a' && c <= 'z')
68        c = c - 'a' + 'A';
69    if (c >= '"' && c <= '_') {
70        return morsetable[c - '"'];
71    } else
72        return 0;
73}
74
75static inline unsigned long dit_len(struct morse_trig_data *morse_data)
76{
77    return MORSE_DIT_LEN*morse_data->delay;
78}
79
80static inline unsigned long dah_len(struct morse_trig_data *morse_data)
81{
82    return MORSE_DAH_LEN*morse_data->delay;
83}
84
85static inline unsigned long space_len(struct morse_trig_data *morse_data)
86{
87    return MORSE_SPACE_LEN*morse_data->delay;
88}
89
90static void morse_timer_function(unsigned long data)
91{
92    struct led_classdev *led_cdev = (struct led_classdev *)data;
93    struct morse_trig_data *morse_data = led_cdev->trigger_data;
94    unsigned long brightness = LED_OFF;
95    unsigned long delay = 0;
96
97    if (!morse_data->msg)
98        goto set_led;
99
100    switch (morse_data->state) {
101    case MORSE_STATE_BLINK_START:
102        /* Starting a new blink. We have a valid code in morse. */
103        delay = (morse_data->morse & 001) ? dah_len(morse_data):
104            dit_len(morse_data);
105        brightness = LED_FULL;
106        morse_data->state = MORSE_STATE_BLINK_STOP;
107        morse_data->morse >>= 1;
108        break;
109    case MORSE_STATE_BLINK_STOP:
110        /* Coming off of a blink. */
111        morse_data->state = MORSE_STATE_BLINK_START;
112
113        if (morse_data->morse > 1) {
114            /* Not done yet, just a one-dit pause. */
115            delay = dit_len(morse_data);
116            break;
117        }
118
119        /* Get a new char, figure out how much space. */
120        /* First time through */
121        if (!morse_data->msgpos)
122            morse_data->msgpos = (char *)morse_data->msg;
123
124        if (!*morse_data->msgpos) {
125            /* Repeating */
126            morse_data->msgpos = (char *)morse_data->msg;
127            delay = space_len(morse_data);
128        } else {
129            /* Inter-letter space */
130            delay = dah_len(morse_data);
131        }
132
133        if (!(morse_data->morse = tomorse(*morse_data->msgpos))) {
134            delay = space_len(morse_data);
135            /* And get us back here */
136            morse_data->state = MORSE_STATE_BLINK_STOP;
137        }
138        morse_data->msgpos++;
139        break;
140    }
141
142    mod_timer(&morse_data->timer, jiffies + msecs_to_jiffies(delay));
143
144set_led:
145    led_set_brightness(led_cdev, brightness);
146}
147
148static ssize_t _morse_delay_show(struct led_classdev *led_cdev, char *buf)
149{
150    struct morse_trig_data *morse_data = led_cdev->trigger_data;
151
152    sprintf(buf, "%lu\n", morse_data->delay);
153
154    return strlen(buf) + 1;
155}
156
157static ssize_t _morse_delay_store(struct led_classdev *led_cdev,
158        const char *buf, size_t size)
159{
160    struct morse_trig_data *morse_data = led_cdev->trigger_data;
161    char *after;
162    unsigned long state = simple_strtoul(buf, &after, 10);
163    size_t count = after - buf;
164    int ret = -EINVAL;
165
166    if (*after && isspace(*after))
167        count++;
168
169    if (count == size) {
170        morse_data->delay = state;
171        mod_timer(&morse_data->timer, jiffies + 1);
172        ret = count;
173    }
174
175    return ret;
176}
177
178static ssize_t _morse_msg_show(struct led_classdev *led_cdev, char *buf)
179{
180    struct morse_trig_data *morse_data = led_cdev->trigger_data;
181
182    if (!morse_data->msg)
183        sprintf(buf, "<none>\n");
184    else
185        sprintf(buf, "%s\n", morse_data->msg);
186
187    return strlen(buf) + 1;
188}
189
190static ssize_t _morse_msg_store(struct led_classdev *led_cdev,
191        const char *buf, size_t size)
192{
193    struct morse_trig_data *morse_data = led_cdev->trigger_data;
194    char *m;
195
196    m = kmalloc(size, GFP_KERNEL);
197    if (!m)
198        return -ENOMEM;
199
200    memcpy(m,buf,size);
201    m[size]='\0';
202
203    if (morse_data->msg)
204        kfree(morse_data->msg);
205
206    morse_data->msg = m;
207    morse_data->msgpos = NULL;
208    morse_data->state = MORSE_STATE_BLINK_STOP;
209
210    mod_timer(&morse_data->timer, jiffies + 1);
211
212    return size;
213}
214
215#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
216static ssize_t morse_delay_show(struct device *dev,
217        struct device_attribute *attr, char *buf)
218{
219    struct led_classdev *led_cdev = dev_get_drvdata(dev);
220
221    return _morse_delay_show(led_cdev, buf);
222}
223
224static ssize_t morse_delay_store(struct device *dev,
225        struct device_attribute *attr, const char *buf, size_t size)
226{
227    struct led_classdev *led_cdev = dev_get_drvdata(dev);
228
229    return _morse_delay_store(led_cdev, buf, size);
230}
231
232static ssize_t morse_msg_show(struct device *dev,
233        struct device_attribute *attr, char *buf)
234{
235    struct led_classdev *led_cdev = dev_get_drvdata(dev);
236
237    return _morse_msg_show(led_cdev, buf);
238}
239
240static ssize_t morse_msg_store(struct device *dev,
241        struct device_attribute *attr, const char *buf, size_t size)
242{
243    struct led_classdev *led_cdev = dev_get_drvdata(dev);
244
245    return _morse_msg_store(led_cdev, buf, size);
246}
247
248static DEVICE_ATTR(delay, 0644, morse_delay_show, morse_delay_store);
249static DEVICE_ATTR(message, 0644, morse_msg_show, morse_msg_store);
250
251#define led_device_create_file(leddev, attr) \
252    device_create_file(leddev->dev, &dev_attr_ ## attr)
253#define led_device_remove_file(leddev, attr) \
254    device_remove_file(leddev->dev, &dev_attr_ ## attr)
255
256#else
257static ssize_t morse_delay_show(struct class_device *dev, char *buf)
258{
259    struct led_classdev *led_cdev = class_get_devdata(dev);
260
261    return _morse_delay_show(led_cdev, buf);
262}
263
264static ssize_t morse_delay_store(struct class_device *dev, const char *buf,
265        size_t size)
266{
267    struct led_classdev *led_cdev = class_get_devdata(dev);
268
269    return _morse_delay_store(led_cdev, buf, size);
270}
271
272static ssize_t morse_msg_show(struct class_device *dev, char *buf)
273{
274    struct led_classdev *led_cdev = class_get_devdata(dev);
275
276    return _morse_msg_show(led_cdev, buf);
277}
278
279static ssize_t morse_msg_store(struct class_device *dev, const char *buf,
280                size_t size)
281{
282    struct led_classdev *led_cdev = class_get_devdata(dev);
283
284    return _morse_msg_store(led_cdev, buf, size);
285}
286
287static CLASS_DEVICE_ATTR(delay, 0644, morse_delay_show, morse_delay_store);
288static CLASS_DEVICE_ATTR(message, 0644, morse_msg_show, morse_msg_store);
289
290#define led_device_create_file(leddev, attr) \
291    class_device_create_file(leddev->class_dev, &class_device_attr_ ## attr)
292#define led_device_remove_file(leddev, attr) \
293    class_device_remove_file(leddev->class_dev, &class_device_attr_ ## attr)
294
295#endif
296
297static void morse_trig_activate(struct led_classdev *led_cdev)
298{
299    struct morse_trig_data *morse_data;
300    int rc;
301
302    morse_data = kzalloc(sizeof(*morse_data), GFP_KERNEL);
303    if (!morse_data)
304        return;
305
306    morse_data->delay = MORSE_DELAY_BASE;
307    init_timer(&morse_data->timer);
308    morse_data->timer.function = morse_timer_function;
309    morse_data->timer.data = (unsigned long)led_cdev;
310
311    rc = led_device_create_file(led_cdev, delay);
312    if (rc) goto err;
313
314    rc = led_device_create_file(led_cdev, message);
315    if (rc) goto err_delay;
316
317    led_cdev->trigger_data = morse_data;
318
319    return;
320
321err_delay:
322    led_device_remove_file(led_cdev, delay);
323err:
324    kfree(morse_data);
325}
326
327static void morse_trig_deactivate(struct led_classdev *led_cdev)
328{
329    struct morse_trig_data *morse_data = led_cdev->trigger_data;
330
331    if (!morse_data)
332        return;
333
334    led_device_remove_file(led_cdev, message);
335    led_device_remove_file(led_cdev, delay);
336
337    del_timer_sync(&morse_data->timer);
338    if (morse_data->msg)
339        kfree(morse_data->msg);
340
341    kfree(morse_data);
342}
343
344static struct led_trigger morse_led_trigger = {
345    .name = "morse",
346    .activate = morse_trig_activate,
347    .deactivate = morse_trig_deactivate,
348};
349
350static int __init morse_trig_init(void)
351{
352    return led_trigger_register(&morse_led_trigger);
353}
354
355static void __exit morse_trig_exit(void)
356{
357    led_trigger_unregister(&morse_led_trigger);
358}
359
360module_init(morse_trig_init);
361module_exit(morse_trig_exit);
362
363MODULE_AUTHOR("Gabor Juhos <juhosg at openwrt.org>");
364MODULE_DESCRIPTION("Morse LED trigger");
365MODULE_LICENSE("GPL");
target/linux/generic-2.6/files-2.6.31/drivers/leds/ledtrig-netdev.c
1/*
2 * LED Kernel Netdev Trigger
3 *
4 * Toggles the LED to reflect the link and traffic state of a named net device
5 *
6 * Copyright 2007 Oliver Jowett <oliver@opencloud.com>
7 *
8 * Derived from ledtrig-timer.c which is:
9 * Copyright 2005-2006 Openedhand Ltd.
10 * Author: Richard Purdie <rpurdie@openedhand.com>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 *
16 */
17
18#include <linux/module.h>
19#include <linux/jiffies.h>
20#include <linux/kernel.h>
21#include <linux/init.h>
22#include <linux/list.h>
23#include <linux/spinlock.h>
24#include <linux/device.h>
25#include <linux/sysdev.h>
26#include <linux/netdevice.h>
27#include <linux/timer.h>
28#include <linux/ctype.h>
29#include <linux/leds.h>
30#include <linux/version.h>
31
32#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
33#include <net/net_namespace.h>
34#endif
35
36#include "leds.h"
37
38/*
39 * Configurable sysfs attributes:
40 *
41 * device_name - network device name to monitor
42 *
43 * interval - duration of LED blink, in milliseconds
44 *
45 * mode - either "none" (LED is off) or a space separated list of one or more of:
46 * link: LED's normal state reflects whether the link is up (has carrier) or not
47 * tx: LED blinks on transmitted data
48 * rx: LED blinks on receive data
49 *
50 * Some suggestions:
51 *
52 * Simple link status LED:
53 * $ echo netdev >someled/trigger
54 * $ echo eth0 >someled/device_name
55 * $ echo link >someled/mode
56 *
57 * Ethernet-style link/activity LED:
58 * $ echo netdev >someled/trigger
59 * $ echo eth0 >someled/device_name
60 * $ echo "link tx rx" >someled/mode
61 *
62 * Modem-style tx/rx LEDs:
63 * $ echo netdev >led1/trigger
64 * $ echo ppp0 >led1/device_name
65 * $ echo tx >led1/mode
66 * $ echo netdev >led2/trigger
67 * $ echo ppp0 >led2/device_name
68 * $ echo rx >led2/mode
69 *
70 */
71
72#define MODE_LINK 1
73#define MODE_TX 2
74#define MODE_RX 4
75
76struct led_netdev_data {
77    rwlock_t lock;
78
79    struct timer_list timer;
80    struct notifier_block notifier;
81
82    struct led_classdev *led_cdev;
83    struct net_device *net_dev;
84
85    char device_name[IFNAMSIZ];
86    unsigned interval;
87    unsigned mode;
88    unsigned link_up;
89    unsigned last_activity;
90};
91
92static void set_baseline_state(struct led_netdev_data *trigger_data)
93{
94    if ((trigger_data->mode & MODE_LINK) != 0 && trigger_data->link_up)
95        led_set_brightness(trigger_data->led_cdev, LED_FULL);
96    else
97        led_set_brightness(trigger_data->led_cdev, LED_OFF);
98
99    if ((trigger_data->mode & (MODE_TX | MODE_RX)) != 0 && trigger_data->link_up)
100        mod_timer(&trigger_data->timer, jiffies + trigger_data->interval);
101    else
102        del_timer(&trigger_data->timer);
103}
104
105static ssize_t led_device_name_show(struct device *dev,
106                    struct device_attribute *attr, char *buf)
107{
108    struct led_classdev *led_cdev = dev_get_drvdata(dev);
109    struct led_netdev_data *trigger_data = led_cdev->trigger_data;
110
111    read_lock(&trigger_data->lock);
112    sprintf(buf, "%s\n", trigger_data->device_name);
113    read_unlock(&trigger_data->lock);
114
115    return strlen(buf) + 1;
116}
117
118#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
119extern struct net init_net;
120#endif
121
122static ssize_t led_device_name_store(struct device *dev,
123                     struct device_attribute *attr, const char *buf, size_t size)
124{
125    struct led_classdev *led_cdev = dev_get_drvdata(dev);
126    struct led_netdev_data *trigger_data = led_cdev->trigger_data;
127
128    if (size < 0 || size >= IFNAMSIZ)
129        return -EINVAL;
130
131    write_lock(&trigger_data->lock);
132
133    strcpy(trigger_data->device_name, buf);
134    if (size > 0 && trigger_data->device_name[size-1] == '\n')
135        trigger_data->device_name[size-1] = 0;
136
137    if (trigger_data->device_name[0] != 0) {
138        /* check for existing device to update from */
139#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
140        trigger_data->net_dev = dev_get_by_name(&init_net, trigger_data->device_name);
141#else
142        trigger_data->net_dev = dev_get_by_name(trigger_data->device_name);
143#endif
144        if (trigger_data->net_dev != NULL)
145            trigger_data->link_up = (dev_get_flags(trigger_data->net_dev) & IFF_LOWER_UP) != 0;
146        set_baseline_state(trigger_data); /* updates LEDs, may start timers */
147    }
148
149    write_unlock(&trigger_data->lock);
150    return size;
151}
152
153static DEVICE_ATTR(device_name, 0644, led_device_name_show, led_device_name_store);
154
155static ssize_t led_mode_show(struct device *dev,
156                 struct device_attribute *attr, char *buf)
157{
158    struct led_classdev *led_cdev = dev_get_drvdata(dev);
159    struct led_netdev_data *trigger_data = led_cdev->trigger_data;
160
161    read_lock(&trigger_data->lock);
162
163    if (trigger_data->mode == 0) {
164        strcpy(buf, "none\n");
165    } else {
166        if (trigger_data->mode & MODE_LINK)
167            strcat(buf, "link ");
168        if (trigger_data->mode & MODE_TX)
169            strcat(buf, "tx ");
170        if (trigger_data->mode & MODE_RX)
171            strcat(buf, "rx ");
172        strcat(buf, "\n");
173    }
174
175    read_unlock(&trigger_data->lock);
176
177    return strlen(buf)+1;
178}
179
180static ssize_t led_mode_store(struct device *dev,
181                  struct device_attribute *attr, const char *buf, size_t size)
182{
183    struct led_classdev *led_cdev = dev_get_drvdata(dev);
184    struct led_netdev_data *trigger_data = led_cdev->trigger_data;
185    char copybuf[1024];
186    int new_mode = -1;
187    char *p, *token;
188
189    /* take a copy since we don't want to trash the inbound buffer when using strsep */
190    strncpy(copybuf, buf, sizeof(copybuf));
191    copybuf[1023] = 0;
192    p = copybuf;
193
194    while ((token = strsep(&p, " \t\n")) != NULL) {
195        if (!*token)
196            continue;
197
198        if (new_mode == -1)
199            new_mode = 0;
200
201        if (!strcmp(token, "none"))
202            new_mode = 0;
203        else if (!strcmp(token, "tx"))
204            new_mode |= MODE_TX;
205        else if (!strcmp(token, "rx"))
206            new_mode |= MODE_RX;
207        else if (!strcmp(token, "link"))
208            new_mode |= MODE_LINK;
209        else
210            return -EINVAL;
211    }
212
213    if (new_mode == -1)
214        return -EINVAL;
215
216    write_lock(&trigger_data->lock);
217    trigger_data->mode = new_mode;
218    set_baseline_state(trigger_data);
219    write_unlock(&trigger_data->lock);
220
221    return size;
222}
223
224static DEVICE_ATTR(mode, 0644, led_mode_show, led_mode_store);
225
226static ssize_t led_interval_show(struct device *dev,
227                 struct device_attribute *attr, char *buf)
228{
229    struct led_classdev *led_cdev = dev_get_drvdata(dev);
230    struct led_netdev_data *trigger_data = led_cdev->trigger_data;
231
232    read_lock(&trigger_data->lock);
233    sprintf(buf, "%u\n", jiffies_to_msecs(trigger_data->interval));
234    read_unlock(&trigger_data->lock);
235
236    return strlen(buf) + 1;
237}
238
239static ssize_t led_interval_store(struct device *dev,
240                  struct device_attribute *attr, const char *buf, size_t size)
241{
242    struct led_classdev *led_cdev = dev_get_drvdata(dev);
243    struct led_netdev_data *trigger_data = led_cdev->trigger_data;
244    int ret = -EINVAL;
245    char *after;
246    unsigned long value = simple_strtoul(buf, &after, 10);
247    size_t count = after - buf;
248
249    if (*after && isspace(*after))
250        count++;
251
252    /* impose some basic bounds on the timer interval */
253    if (count == size && value >= 5 && value <= 10000) {
254        write_lock(&trigger_data->lock);
255        trigger_data->interval = msecs_to_jiffies(value);
256        set_baseline_state(trigger_data); // resets timer
257        write_unlock(&trigger_data->lock);
258        ret = count;
259    }
260
261    return ret;
262}
263
264static DEVICE_ATTR(interval, 0644, led_interval_show, led_interval_store);
265
266static int netdev_trig_notify(struct notifier_block *nb,
267                  unsigned long evt,
268                  void *dv)
269{
270    struct net_device *dev = dv;
271    struct led_netdev_data *trigger_data = container_of(nb, struct led_netdev_data, notifier);
272
273    if (evt != NETDEV_UP && evt != NETDEV_DOWN && evt != NETDEV_CHANGE && evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER)
274        return NOTIFY_DONE;
275
276    write_lock(&trigger_data->lock);
277
278    if (strcmp(dev->name, trigger_data->device_name))
279        goto done;
280
281    if (evt == NETDEV_REGISTER) {
282        if (trigger_data->net_dev != NULL)
283            dev_put(trigger_data->net_dev);
284        dev_hold(dev);
285        trigger_data->net_dev = dev;
286        trigger_data->link_up = 0;
287        goto done;
288    }
289
290    if (evt == NETDEV_UNREGISTER && trigger_data->net_dev != NULL) {
291        dev_put(trigger_data->net_dev);
292        trigger_data->net_dev = NULL;
293        goto done;
294    }
295
296    /* UP / DOWN / CHANGE */
297
298    trigger_data->link_up = (evt != NETDEV_DOWN && netif_carrier_ok(dev));
299    set_baseline_state(trigger_data);
300
301done:
302    write_unlock(&trigger_data->lock);
303    return NOTIFY_DONE;
304}
305
306/* here's the real work! */
307static void netdev_trig_timer(unsigned long arg)
308{
309    struct led_netdev_data *trigger_data = (struct led_netdev_data *)arg;
310    struct net_device_stats *dev_stats;
311    unsigned new_activity;
312
313    write_lock(&trigger_data->lock);
314
315    if (!trigger_data->link_up || !trigger_data->net_dev || (trigger_data->mode & (MODE_TX | MODE_RX)) == 0) {
316        /* we don't need to do timer work, just reflect link state. */
317        led_set_brightness(trigger_data->led_cdev, ((trigger_data->mode & MODE_LINK) != 0 && trigger_data->link_up) ? LED_FULL : LED_OFF);
318        goto no_restart;
319    }
320#ifdef CONFIG_COMPAT_NET_DEV_OPS
321    dev_stats = trigger_data->net_dev->get_stats(trigger_data->net_dev);
322#else
323    dev_stats = trigger_data->net_dev->netdev_ops->ndo_get_stats(trigger_data->net_dev);
324#endif
325    new_activity =
326        ((trigger_data->mode & MODE_TX) ? dev_stats->tx_packets : 0) +
327        ((trigger_data->mode & MODE_RX) ? dev_stats->rx_packets : 0);
328
329    if (trigger_data->mode & MODE_LINK) {
330        /* base state is ON (link present) */
331        /* if there's no link, we don't get this far and the LED is off */
332
333        /* OFF -> ON always */
334        /* ON -> OFF on activity */
335        if (trigger_data->led_cdev->brightness == LED_OFF) {
336            led_set_brightness(trigger_data->led_cdev, LED_FULL);
337        } else if (trigger_data->last_activity != new_activity) {
338            led_set_brightness(trigger_data->led_cdev, LED_OFF);
339        }
340    } else {
341        /* base state is OFF */
342        /* ON -> OFF always */
343        /* OFF -> ON on activity */
344        if (trigger_data->led_cdev->brightness == LED_FULL) {
345            led_set_brightness(trigger_data->led_cdev, LED_OFF);
346        } else if (trigger_data->last_activity != new_activity) {
347            led_set_brightness(trigger_data->led_cdev, LED_FULL);
348        }
349    }
350
351    trigger_data->last_activity = new_activity;
352    mod_timer(&trigger_data->timer, jiffies + trigger_data->interval);
353
354no_restart:
355    write_unlock(&trigger_data->lock);
356}
357
358static void netdev_trig_activate(struct led_classdev *led_cdev)
359{
360    struct led_netdev_data *trigger_data;
361    int rc;
362
363    trigger_data = kzalloc(sizeof(struct led_netdev_data), GFP_KERNEL);
364    if (!trigger_data)
365        return;
366
367    rwlock_init(&trigger_data->lock);
368
369    trigger_data->notifier.notifier_call = netdev_trig_notify;
370    trigger_data->notifier.priority = 10;
371
372    setup_timer(&trigger_data->timer, netdev_trig_timer, (unsigned long) trigger_data);
373
374    trigger_data->led_cdev = led_cdev;
375    trigger_data->net_dev = NULL;
376    trigger_data->device_name[0] = 0;
377
378    trigger_data->mode = 0;
379    trigger_data->interval = msecs_to_jiffies(50);
380    trigger_data->link_up = 0;
381    trigger_data->last_activity = 0;
382
383    led_cdev->trigger_data = trigger_data;
384
385    rc = device_create_file(led_cdev->dev, &dev_attr_device_name);
386    if (rc)
387        goto err_out;
388    rc = device_create_file(led_cdev->dev, &dev_attr_mode);
389    if (rc)
390        goto err_out_device_name;
391    rc = device_create_file(led_cdev->dev, &dev_attr_interval);
392    if (rc)
393        goto err_out_mode;
394
395    register_netdevice_notifier(&trigger_data->notifier);
396    return;
397
398err_out_mode:
399    device_remove_file(led_cdev->dev, &dev_attr_mode);
400err_out_device_name:
401    device_remove_file(led_cdev->dev, &dev_attr_device_name);
402err_out:
403    led_cdev->trigger_data = NULL;
404    kfree(trigger_data);
405}
406
407static void netdev_trig_deactivate(struct led_classdev *led_cdev)
408{
409    struct led_netdev_data *trigger_data = led_cdev->trigger_data;
410
411    if (trigger_data) {
412        unregister_netdevice_notifier(&trigger_data->notifier);
413
414        device_remove_file(led_cdev->dev, &dev_attr_device_name);
415        device_remove_file(led_cdev->dev, &dev_attr_mode);
416        device_remove_file(led_cdev->dev, &dev_attr_interval);
417
418        write_lock(&trigger_data->lock);
419
420        if (trigger_data->net_dev) {
421            dev_put(trigger_data->net_dev);
422            trigger_data->net_dev = NULL;
423        }
424
425        write_unlock(&trigger_data->lock);
426
427        del_timer_sync(&trigger_data->timer);
428
429        kfree(trigger_data);
430    }
431}
432
433static struct led_trigger netdev_led_trigger = {
434    .name = "netdev",
435    .activate = netdev_trig_activate,
436    .deactivate = netdev_trig_deactivate,
437};
438
439static int __init netdev_trig_init(void)
440{
441    return led_trigger_register(&netdev_led_trigger);
442}
443
444static void __exit netdev_trig_exit(void)
445{
446    led_trigger_unregister(&netdev_led_trigger);
447}
448
449module_init(netdev_trig_init);
450module_exit(netdev_trig_exit);
451
452MODULE_AUTHOR("Oliver Jowett <oliver@opencloud.com>");
453MODULE_DESCRIPTION("Netdev LED trigger");
454MODULE_LICENSE("GPL");
target/linux/generic-2.6/files-2.6.31/drivers/net/phy/ar8216.c
1/*
2 * ar8216.c: AR8216 switch driver
3 *
4 * Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <linux/if.h>
18#include <linux/module.h>
19#include <linux/init.h>
20#include <linux/list.h>
21#include <linux/if_ether.h>
22#include <linux/skbuff.h>
23#include <linux/netdevice.h>
24#include <linux/netlink.h>
25#include <linux/bitops.h>
26#include <net/genetlink.h>
27#include <linux/switch.h>
28#include <linux/delay.h>
29#include <linux/phy.h>
30#include <linux/netdevice.h>
31#include <linux/etherdevice.h>
32#include "ar8216.h"
33
34
35struct ar8216_priv {
36    struct switch_dev dev;
37    struct phy_device *phy;
38    u32 (*read)(struct ar8216_priv *priv, int reg);
39    void (*write)(struct ar8216_priv *priv, int reg, u32 val);
40    const struct net_device_ops *ndo_old;
41    struct net_device_ops ndo;
42
43    /* all fields below are cleared on reset */
44    bool vlan;
45    u8 vlan_id[AR8216_NUM_VLANS];
46    u8 vlan_table[AR8216_NUM_VLANS];
47    u8 vlan_tagged;
48    u16 pvid[AR8216_NUM_PORTS];
49};
50static struct switch_dev athdev;
51
52#define to_ar8216(_dev) container_of(_dev, struct ar8216_priv, dev)
53
54static inline void
55split_addr(u32 regaddr, u16 *r1, u16 *r2, u16 *page)
56{
57    regaddr >>= 1;
58    *r1 = regaddr & 0x1e;
59
60    regaddr >>= 5;
61    *r2 = regaddr & 0x7;
62
63    regaddr >>= 3;
64    *page = regaddr & 0x1ff;
65}
66
67static u32
68ar8216_mii_read(struct ar8216_priv *priv, int reg)
69{
70    struct phy_device *phy = priv->phy;
71    u16 r1, r2, page;
72    u16 lo, hi;
73
74    split_addr((u32) reg, &r1, &r2, &page);
75    phy->bus->write(phy->bus, 0x18, 0, page);
76    msleep(1); /* wait for the page switch to propagate */
77    lo = phy->bus->read(phy->bus, 0x10 | r2, r1);
78    hi = phy->bus->read(phy->bus, 0x10 | r2, r1 + 1);
79
80    return (hi << 16) | lo;
81}
82
83static void
84ar8216_mii_write(struct ar8216_priv *priv, int reg, u32 val)
85{
86    struct phy_device *phy = priv->phy;
87    u16 r1, r2, r3;
88    u16 lo, hi;
89
90    split_addr((u32) reg, &r1, &r2, &r3);
91    phy->bus->write(phy->bus, 0x18, 0, r3);
92    msleep(1); /* wait for the page switch to propagate */
93
94    lo = val & 0xffff;
95    hi = (u16) (val >> 16);
96    phy->bus->write(phy->bus, 0x10 | r2, r1 + 1, hi);
97    phy->bus->write(phy->bus, 0x10 | r2, r1, lo);
98}
99
100static u32
101ar8216_rmw(struct ar8216_priv *priv, int reg, u32 mask, u32 val)
102{
103    u32 v;
104
105    v = priv->read(priv, reg);
106    v &= ~mask;
107    v |= val;
108    priv->write(priv, reg, v);
109
110    return v;
111}
112
113static int
114ar8216_set_vlan(struct switch_dev *dev, const struct switch_attr *attr,
115                struct switch_val *val)
116{
117    struct ar8216_priv *priv = to_ar8216(dev);
118    priv->vlan = !!val->value.i;
119    return 0;
120}
121
122static int
123ar8216_get_vlan(struct switch_dev *dev, const struct switch_attr *attr,
124                struct switch_val *val)
125{
126    struct ar8216_priv *priv = to_ar8216(dev);
127    val->value.i = priv->vlan;
128    return 0;
129}
130
131
132static int
133ar8216_set_pvid(struct switch_dev *dev, int port, int vlan)
134{
135    struct ar8216_priv *priv = to_ar8216(dev);
136    priv->pvid[port] = vlan;
137    return 0;
138}
139
140static int
141ar8216_get_pvid(struct switch_dev *dev, int port, int *vlan)
142{
143    struct ar8216_priv *priv = to_ar8216(dev);
144    *vlan = priv->pvid[port];
145    return 0;
146}
147
148static int
149ar8216_set_vid(struct switch_dev *dev, const struct switch_attr *attr,
150                struct switch_val *val)
151{
152    struct ar8216_priv *priv = to_ar8216(dev);
153    priv->vlan_id[val->port_vlan] = val->value.i;
154    return 0;
155}
156
157static int
158ar8216_get_vid(struct switch_dev *dev, const struct switch_attr *attr,
159                struct switch_val *val)
160{
161    struct ar8216_priv *priv = to_ar8216(dev);
162    val->value.i = priv->vlan_id[val->port_vlan];
163    return 0;
164}
165
166
167static int
168ar8216_mangle_tx(struct sk_buff *skb, struct net_device *dev)
169{
170    struct ar8216_priv *priv = dev->phy_ptr;
171    unsigned char *buf;
172
173    if (unlikely(!priv))
174        goto error;
175
176    if (!priv->vlan)
177        goto send;
178
179    if (unlikely(skb_headroom(skb) < 2)) {
180        if (pskb_expand_head(skb, 2, 0, GFP_ATOMIC) < 0)
181            goto error;
182    }
183
184    buf = skb_push(skb, 2);
185    buf[0] = 0x10;
186    buf[1] = 0x80;
187
188send:
189    return priv->ndo_old->ndo_start_xmit(skb, dev);
190
191error:
192    dev_kfree_skb_any(skb);
193    return 0;
194}
195
196static int
197ar8216_mangle_rx(struct sk_buff *skb, int napi)
198{
199    struct ar8216_priv *priv;
200    struct net_device *dev;
201    unsigned char *buf;
202    int port, vlan;
203
204    dev = skb->dev;
205    if (!dev)
206        goto error;
207
208    priv = dev->phy_ptr;
209    if (!priv)
210        goto error;
211
212    /* don't strip the header if vlan mode is disabled */
213    if (!priv->vlan)
214        goto recv;
215
216    /* strip header, get vlan id */
217    buf = skb->data;
218    skb_pull(skb, 2);
219
220    /* check for vlan header presence */
221    if ((buf[12 + 2] != 0x81) || (buf[13 + 2] != 0x00))
222        goto recv;
223
224    port = buf[0] & 0xf;
225
226    /* no need to fix up packets coming from a tagged source */
227    if (priv->vlan_tagged & (1 << port))
228        goto recv;
229
230    /* lookup port vid from local table, the switch passes an invalid vlan id */
231    vlan = priv->pvid[port];
232
233    buf[14 + 2] &= 0xf0;
234    buf[14 + 2] |= vlan >> 8;
235    buf[15 + 2] = vlan & 0xff;
236
237recv:
238    skb->protocol = eth_type_trans(skb, skb->dev);
239
240    if (napi)
241        return netif_receive_skb(skb);
242    else
243        return netif_rx(skb);
244
245error:
246    /* no vlan? eat the packet! */
247    dev_kfree_skb_any(skb);
248    return 0;
249}
250
251static int
252ar8216_netif_rx(struct sk_buff *skb)
253{
254    return ar8216_mangle_rx(skb, 0);
255}
256
257static int
258ar8216_netif_receive_skb(struct sk_buff *skb)
259{
260    return ar8216_mangle_rx(skb, 1);
261}
262
263
264static struct switch_attr ar8216_globals[] = {
265    {
266        .type = SWITCH_TYPE_INT,
267        .name = "enable_vlan",
268        .description = "Enable VLAN mode",
269        .set = ar8216_set_vlan,
270        .get = ar8216_get_vlan,
271        .max = 1
272    },
273};
274
275static struct switch_attr ar8216_port[] = {
276};
277
278static struct switch_attr ar8216_vlan[] = {
279    {
280        .type = SWITCH_TYPE_INT,
281        .name = "pvid",
282        .description = "VLAN ID",
283        .set = ar8216_set_vid,
284        .get = ar8216_get_vid,
285        .max = 4095,
286    },
287};
288
289
290static int
291ar8216_get_ports(struct switch_dev *dev, struct switch_val *val)
292{
293    struct ar8216_priv *priv = to_ar8216(dev);
294    u8 ports = priv->vlan_table[val->port_vlan];
295    int i;
296
297    val->len = 0;
298    for (i = 0; i < AR8216_NUM_PORTS; i++) {
299        struct switch_port *p;
300
301        if (!(ports & (1 << i)))
302            continue;
303
304        p = &val->value.ports[val->len++];
305        p->id = i;
306        if (priv->vlan_tagged & (1 << i))
307            p->flags = (1 << SWITCH_PORT_FLAG_TAGGED);
308        else
309            p->flags = 0;
310    }
311    return 0;
312}
313
314static int
315ar8216_set_ports(struct switch_dev *dev, struct switch_val *val)
316{
317    struct ar8216_priv *priv = to_ar8216(dev);
318    u8 *vt = &priv->vlan_table[val->port_vlan];
319    int i, j;
320
321    *vt = 0;
322    for (i = 0; i < val->len; i++) {
323        struct switch_port *p = &val->value.ports[i];
324
325        if (p->flags & (1 << SWITCH_PORT_FLAG_TAGGED))
326            priv->vlan_tagged |= (1 << p->id);
327        else {
328            priv->vlan_tagged &= ~(1 << p->id);
329            priv->pvid[p->id] = val->port_vlan;
330
331            /* make sure that an untagged port does not
332             * appear in other vlans */
333            for (j = 0; j < AR8216_NUM_VLANS; j++) {
334                if (j == val->port_vlan)
335                    continue;
336                priv->vlan_table[j] &= ~(1 << p->id);
337            }
338        }
339
340        *vt |= 1 << p->id;
341    }
342    return 0;
343}
344
345static int
346ar8216_wait_bit(struct ar8216_priv *priv, int reg, u32 mask, u32 val)
347{
348    int timeout = 20;
349
350    while ((priv->read(priv, reg) & mask) != val) {
351        if (timeout-- <= 0) {
352            printk(KERN_ERR "ar8216: timeout waiting for operation to complete\n");
353            return 1;
354        }
355    }
356    return 0;
357}
358
359static void
360ar8216_vtu_op(struct ar8216_priv *priv, u32 op, u32 val)
361{
362    if (ar8216_wait_bit(priv, AR8216_REG_VTU, AR8216_VTU_ACTIVE, 0))
363        return;
364    if ((op & AR8216_VTU_OP) == AR8216_VTU_OP_LOAD) {
365        val &= AR8216_VTUDATA_MEMBER;
366        val |= AR8216_VTUDATA_VALID;
367        priv->write(priv, AR8216_REG_VTU_DATA, val);
368    }
369    op |= AR8216_VTU_ACTIVE;
370    priv->write(priv, AR8216_REG_VTU, op);
371}
372
373static int
374ar8216_hw_apply(struct switch_dev *dev)
375{
376    struct ar8216_priv *priv = to_ar8216(dev);
377    u8 portmask[AR8216_NUM_PORTS];
378    int i, j;
379
380    /* flush all vlan translation unit entries */
381    ar8216_vtu_op(priv, AR8216_VTU_OP_FLUSH, 0);
382
383    memset(portmask, 0, sizeof(portmask));
384    if (priv->vlan) {
385        /* calculate the port destination masks and load vlans
386         * into the vlan translation unit */
387        for (j = 0; j < AR8216_NUM_VLANS; j++) {
388            u8 vp = priv->vlan_table[j];
389
390            if (!vp)
391                continue;
392
393            for (i = 0; i < AR8216_NUM_PORTS; i++) {
394                u8 mask = (1 << i);
395                if (vp & mask)
396                    portmask[i] |= vp & ~mask;
397            }
398
399            if (!priv->vlan_table[j])
400                continue;
401
402            ar8216_vtu_op(priv,
403                AR8216_VTU_OP_LOAD |
404                (priv->vlan_id[j] << AR8216_VTU_VID_S),
405                priv->vlan_table[j]);
406        }
407    } else {
408        /* vlan disabled:
409         * isolate all ports, but connect them to the cpu port */
410        for (i = 0; i < AR8216_NUM_PORTS; i++) {
411            if (i == AR8216_PORT_CPU)
412                continue;
413
414            portmask[i] = 1 << AR8216_PORT_CPU;
415            portmask[AR8216_PORT_CPU] |= (1 << i);
416        }
417    }
418
419    /* update the port destination mask registers and tag settings */
420    for (i = 0; i < AR8216_NUM_PORTS; i++) {
421        int egress, ingress;
422        int pvid;
423
424        if (priv->vlan) {
425            pvid = priv->vlan_id[priv->pvid[i]];
426        } else {
427            pvid = i;
428        }
429
430        if (priv->vlan && (priv->vlan_tagged & (1 << i))) {
431            egress = AR8216_OUT_ADD_VLAN;
432        } else {
433            egress = AR8216_OUT_STRIP_VLAN;
434        }
435        ingress = AR8216_IN_SECURE;
436
437        ar8216_rmw(priv, AR8216_REG_PORT_CTRL(i),
438            AR8216_PORT_CTRL_LEARN | AR8216_PORT_CTRL_VLAN_MODE |
439            AR8216_PORT_CTRL_SINGLE_VLAN | AR8216_PORT_CTRL_STATE |
440            AR8216_PORT_CTRL_HEADER | AR8216_PORT_CTRL_LEARN_LOCK,
441            AR8216_PORT_CTRL_LEARN |
442              (priv->vlan && i == AR8216_PORT_CPU ?
443               AR8216_PORT_CTRL_HEADER : 0) |
444              (egress << AR8216_PORT_CTRL_VLAN_MODE_S) |
445              (AR8216_PORT_STATE_FORWARD << AR8216_PORT_CTRL_STATE_S));
446
447        ar8216_rmw(priv, AR8216_REG_PORT_VLAN(i),
448            AR8216_PORT_VLAN_DEST_PORTS | AR8216_PORT_VLAN_MODE |
449              AR8216_PORT_VLAN_DEFAULT_ID,
450            (portmask[i] << AR8216_PORT_VLAN_DEST_PORTS_S) |
451              (ingress << AR8216_PORT_VLAN_MODE_S) |
452              (pvid << AR8216_PORT_VLAN_DEFAULT_ID_S));
453    }
454
455    return 0;
456}
457
458static int
459ar8216_reset_switch(struct switch_dev *dev)
460{
461    struct ar8216_priv *priv = to_ar8216(dev);
462    int i;
463
464    memset(&priv->vlan, 0, sizeof(struct ar8216_priv) -
465        offsetof(struct ar8216_priv, vlan));
466    for (i = 0; i < AR8216_NUM_VLANS; i++) {
467        priv->vlan_id[i] = i;
468    }
469    for (i = 0; i < AR8216_NUM_PORTS; i++) {
470        /* Enable port learning and tx */
471        priv->write(priv, AR8216_REG_PORT_CTRL(i),
472            AR8216_PORT_CTRL_LEARN |
473            (4 << AR8216_PORT_CTRL_STATE_S));
474
475        priv->write(priv, AR8216_REG_PORT_VLAN(i), 0);
476
477        /* Configure all PHYs */
478        if (i == AR8216_PORT_CPU) {
479            priv->write(priv, AR8216_REG_PORT_STATUS(i),
480                AR8216_PORT_STATUS_LINK_UP |
481                AR8216_PORT_STATUS_SPEED |
482                AR8216_PORT_STATUS_TXMAC |
483                AR8216_PORT_STATUS_RXMAC |
484                AR8216_PORT_STATUS_DUPLEX);
485        } else {
486            priv->write(priv, AR8216_REG_PORT_STATUS(i),
487                AR8216_PORT_STATUS_LINK_AUTO);
488        }
489    }
490    /* XXX: undocumented magic from atheros, required! */
491    priv->write(priv, 0x38, 0xc000050e);
492
493    ar8216_rmw(priv, AR8216_REG_GLOBAL_CTRL,
494        AR8216_GCTRL_MTU, 1518 + 8 + 2);
495
496    return ar8216_hw_apply(dev);
497}
498
499static int
500ar8216_config_init(struct phy_device *pdev)
501{
502    struct ar8216_priv *priv;
503    struct net_device *dev = pdev->attached_dev;
504    int ret;
505
506    printk("%s: AR8216 PHY driver attached.\n", pdev->attached_dev->name);
507    pdev->supported = ADVERTISED_100baseT_Full;
508    pdev->advertising = ADVERTISED_100baseT_Full;
509
510    priv = kzalloc(sizeof(struct ar8216_priv), GFP_KERNEL);
511    if (priv == NULL)
512        return -ENOMEM;
513
514    priv->phy = pdev;
515    priv->read = ar8216_mii_read;
516    priv->write = ar8216_mii_write;
517    memcpy(&priv->dev, &athdev, sizeof(struct switch_dev));
518    pdev->priv = priv;
519    if ((ret = register_switch(&priv->dev, pdev->attached_dev)) < 0) {
520        kfree(priv);
521        goto done;
522    }
523
524    ret = ar8216_reset_switch(&priv->dev);
525    if (ret)
526        goto done;
527
528    dev->phy_ptr = priv;
529    pdev->pkt_align = 2;
530    pdev->netif_receive_skb = ar8216_netif_receive_skb;
531    pdev->netif_rx = ar8216_netif_rx;
532
533    priv->ndo_old = dev->netdev_ops;
534    memcpy(&priv->ndo, priv->ndo_old, sizeof(struct net_device_ops));
535    priv->ndo.ndo_start_xmit = ar8216_mangle_tx;
536    dev->netdev_ops = &priv->ndo;
537
538done:
539    return ret;
540}
541
542static int
543ar8216_read_status(struct phy_device *phydev)
544{
545    struct ar8216_priv *priv = phydev->priv;
546
547    phydev->speed = SPEED_100;
548    phydev->duplex = DUPLEX_FULL;
549    phydev->state = PHY_UP;
550
551    /* flush the address translation unit */
552    if (ar8216_wait_bit(priv, AR8216_REG_ATU, AR8216_ATU_ACTIVE, 0))
553        return -ETIMEDOUT;
554
555    priv->write(priv, AR8216_REG_ATU, AR8216_ATU_OP_FLUSH);
556
557    return 0;
558}
559
560static int
561ar8216_config_aneg(struct phy_device *phydev)
562{
563    return 0;
564}
565
566static int
567ar8216_probe(struct phy_device *pdev)
568{
569    struct ar8216_priv priv;
570
571    u8 id, rev;
572    u32 val;
573
574    priv.phy = pdev;
575    val = ar8216_mii_read(&priv, AR8216_REG_CTRL);
576    rev = val & 0xff;
577    id = (val >> 8) & 0xff;
578    if ((id != 1) || (rev != 1))
579        return -ENODEV;
580
581    return 0;
582}
583
584static void
585ar8216_remove(struct phy_device *pdev)
586{
587    struct ar8216_priv *priv = pdev->priv;
588    struct net_device *dev = pdev->attached_dev;
589
590    if (!priv)
591        return;
592
593    if (priv->ndo_old && dev)
594        dev->netdev_ops = priv->ndo_old;
595    unregister_switch(&priv->dev);
596    kfree(priv);
597}
598
599/* template */
600static struct switch_dev athdev = {
601    .name = "Atheros AR8216",
602    .cpu_port = AR8216_PORT_CPU,
603    .ports = AR8216_NUM_PORTS,
604    .vlans = AR8216_NUM_VLANS,
605    .attr_global = {
606        .attr = ar8216_globals,
607        .n_attr = ARRAY_SIZE(ar8216_globals),
608    },
609    .attr_port = {
610        .attr = ar8216_port,
611        .n_attr = ARRAY_SIZE(ar8216_port),
612    },
613    .attr_vlan = {
614        .attr = ar8216_vlan,
615        .n_attr = ARRAY_SIZE(ar8216_vlan),
616    },
617    .get_port_pvid = ar8216_get_pvid,
618    .set_port_pvid = ar8216_set_pvid,
619    .get_vlan_ports = ar8216_get_ports,
620    .set_vlan_ports = ar8216_set_ports,
621    .apply_config = ar8216_hw_apply,
622    .reset_switch = ar8216_reset_switch,
623};
624
625static struct phy_driver ar8216_driver = {
626    .name = "Atheros AR8216",
627    .features = PHY_BASIC_FEATURES,
628    .probe = ar8216_probe,
629    .remove = ar8216_remove,
630    .config_init = &ar8216_config_init,
631    .config_aneg = &ar8216_config_aneg,
632    .read_status = &ar8216_read_status,
633    .driver = { .owner = THIS_MODULE },
634};
635
636int __init
637ar8216_init(void)
638{
639    return phy_driver_register(&ar8216_driver);
640}
641
642void __exit
643ar8216_exit(void)
644{
645    phy_driver_unregister(&ar8216_driver);
646}
647
648module_init(ar8216_init);
649module_exit(ar8216_exit);
650MODULE_LICENSE("GPL");
651
target/linux/generic-2.6/files-2.6.31/drivers/net/phy/mvswitch.c
1/*
2 * Marvell 88E6060 switch driver
3 * Copyright (c) 2008 Felix Fietkau <nbd@openwrt.org>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License v2 as published by the
7 * Free Software Foundation
8 */
9#include <linux/kernel.h>
10#include <linux/string.h>
11#include <linux/errno.h>
12#include <linux/unistd.h>
13#include <linux/slab.h>
14#include <linux/interrupt.h>
15#include <linux/init.h>
16#include <linux/delay.h>
17#include <linux/netdevice.h>
18#include <linux/etherdevice.h>
19#include <linux/skbuff.h>
20#include <linux/spinlock.h>
21#include <linux/mm.h>
22#include <linux/module.h>
23#include <linux/mii.h>
24#include <linux/ethtool.h>
25#include <linux/phy.h>
26#include <linux/if_vlan.h>
27
28#include <asm/io.h>
29#include <asm/irq.h>
30#include <asm/uaccess.h>
31#include "mvswitch.h"
32
33/* Undefine this to use trailer mode instead.
34 * I don't know if header mode works with all chips */
35#define HEADER_MODE 1
36
37MODULE_DESCRIPTION("Marvell 88E6060 Switch driver");
38MODULE_AUTHOR("Felix Fietkau");
39MODULE_LICENSE("GPL");
40
41#define MVSWITCH_MAGIC 0x88E6060
42
43struct mvswitch_priv {
44    const struct net_device_ops *ndo_old;
45    struct net_device_ops ndo;
46    struct vlan_group *grp;
47    u8 vlans[16];
48};
49
50#define to_mvsw(_phy) ((struct mvswitch_priv *) (_phy)->priv)
51
52static inline u16
53r16(struct phy_device *phydev, int addr, int reg)
54{
55    return phydev->bus->read(phydev->bus, addr, reg);
56}
57
58static inline void
59w16(struct phy_device *phydev, int addr, int reg, u16 val)
60{
61    phydev->bus->write(phydev->bus, addr, reg, val);
62}
63
64
65static int
66mvswitch_mangle_tx(struct sk_buff *skb, struct net_device *dev)
67{
68    struct mvswitch_priv *priv;
69    char *buf = NULL;
70    u16 vid;
71
72    priv = dev->phy_ptr;
73    if (unlikely(!priv))
74        goto error;
75
76    if (unlikely(skb->len < 16))
77        goto error;
78
79#ifdef HEADER_MODE
80    if (__vlan_hwaccel_get_tag(skb, &vid))
81        goto error;
82
83    if (skb_cloned(skb) || (skb->len <= 62) || (skb_headroom(skb) < MV_HEADER_SIZE)) {
84        if (pskb_expand_head(skb, MV_HEADER_SIZE, (skb->len < 62 ? 62 - skb->len : 0), GFP_ATOMIC))
85            goto error_expand;
86        if (skb->len < 62)
87            skb->len = 62;
88    }
89    buf = skb_push(skb, MV_HEADER_SIZE);
90#else
91    if (__vlan_get_tag(skb, &vid))
92        goto error;
93
94    if (unlikely((vid > 15 || !priv->vlans[vid])))
95        goto error;
96
97    if (skb->len <= 64) {
98        if (pskb_expand_head(skb, 0, 64 + MV_TRAILER_SIZE - skb->len, GFP_ATOMIC))
99            goto error_expand;
100
101        buf = skb->data + 64;
102        skb->len = 64 + MV_TRAILER_SIZE;
103    } else {
104        if (skb_cloned(skb) || unlikely(skb_tailroom(skb) < 4)) {
105            if (pskb_expand_head(skb, 0, 4, GFP_ATOMIC))
106                goto error_expand;
107        }
108        buf = skb_put(skb, 4);
109    }
110
111    /* move the ethernet header 4 bytes forward, overwriting the vlan tag */
112    memmove(skb->data + 4, skb->data, 12);
113    skb->data += 4;
114    skb->len -= 4;
115    skb->mac_header += 4;
116#endif
117
118    if (!buf)
119        goto error;
120
121
122#ifdef HEADER_MODE
123    /* prepend the tag */
124    *((__be16 *) buf) = cpu_to_be16(
125        ((vid << MV_HEADER_VLAN_S) & MV_HEADER_VLAN_M) |
126        ((priv->vlans[vid] << MV_HEADER_PORTS_S) & MV_HEADER_PORTS_M)
127    );
128#else
129    /* append the tag */
130    *((__be32 *) buf) = cpu_to_be32((
131        (MV_TRAILER_OVERRIDE << MV_TRAILER_FLAGS_S) |
132        ((priv->vlans[vid] & MV_TRAILER_PORTS_M) << MV_TRAILER_PORTS_S)
133    ));
134#endif
135
136    return priv->ndo_old->ndo_start_xmit(skb, dev);
137
138error_expand:
139    if (net_ratelimit())
140        printk("%s: failed to expand/update skb for the switch\n", dev->name);
141
142error:
143    /* any errors? drop the packet! */
144    dev_kfree_skb_any(skb);
145    return 0;
146}
147
148static int
149mvswitch_mangle_rx(struct sk_buff *skb, int napi)
150{
151    struct mvswitch_priv *priv;
152    struct net_device *dev;
153    int vlan = -1;
154    unsigned char *buf;
155    int i;
156
157    dev = skb->dev;
158    if (!dev)
159        goto error;
160
161    priv = dev->phy_ptr;
162    if (!priv)
163        goto error;
164
165    if (!priv->grp)
166        goto error;
167
168#ifdef HEADER_MODE
169    buf = skb->data;
170    skb_pull(skb, MV_HEADER_SIZE);
171#else
172    buf = skb->data + skb->len - MV_TRAILER_SIZE;
173    if (buf[0] != 0x80)
174        goto error;
175#endif
176
177    /* look for the vlan matching the incoming port */
178    for (i = 0; i < ARRAY_SIZE(priv->vlans); i++) {
179        if ((1 << buf[1]) & priv->vlans[i])
180            vlan = i;
181    }
182
183    if (vlan == -1)
184        goto error;
185
186    skb->protocol = eth_type_trans(skb, skb->dev);
187
188    if (napi)
189        return vlan_hwaccel_receive_skb(skb, priv->grp, vlan);
190    else
191        return vlan_hwaccel_rx(skb, priv->grp, vlan);
192
193error:
194    /* no vlan? eat the packet! */
195    dev_kfree_skb_any(skb);
196    return 0;
197}
198
199
200static int
201mvswitch_netif_rx(struct sk_buff *skb)
202{
203    return mvswitch_mangle_rx(skb, 0);
204}
205
206static int
207mvswitch_netif_receive_skb(struct sk_buff *skb)
208{
209    return mvswitch_mangle_rx(skb, 1);
210}
211
212
213static void
214mvswitch_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
215{
216    struct mvswitch_priv *priv = dev->phy_ptr;
217    priv->grp = grp;
218}
219
220
221static int
222mvswitch_wait_mask(struct phy_device *pdev, int addr, int reg, u16 mask, u16 val)
223{
224    int i = 100;
225    u16 r;
226
227    do {
228        r = r16(pdev, addr, reg) & mask;
229        if (r == val)
230            return 0;
231    } while(--i > 0);
232    return -ETIMEDOUT;
233}
234
235static int
236mvswitch_config_init(struct phy_device *pdev)
237{
238    struct mvswitch_priv *priv = to_mvsw(pdev);
239    struct net_device *dev = pdev->attached_dev;
240    u8 vlmap = 0;
241    int i;
242
243    if (!dev)
244        return -EINVAL;
245
246    printk("%s: Marvell 88E6060 PHY driver attached.\n", dev->name);
247    pdev->supported = ADVERTISED_100baseT_Full;
248    pdev->advertising = ADVERTISED_100baseT_Full;
249    dev->phy_ptr = priv;
250    dev->irq = PHY_POLL;
251
252    /* initialize default vlans */
253    for (i = 0; i < MV_PORTS; i++)
254        priv->vlans[(i == MV_WANPORT ? 2 : 1)] |= (1 << i);
255
256    /* before entering reset, disable all ports */
257    for (i = 0; i < MV_PORTS; i++)
258        w16(pdev, MV_PORTREG(CONTROL, i), 0x00);
259
260    msleep(2); /* wait for the status change to settle in */
261
262    /* put the ATU in reset */
263    w16(pdev, MV_SWITCHREG(ATU_CTRL), MV_ATUCTL_RESET);
264
265    i = mvswitch_wait_mask(pdev, MV_SWITCHREG(ATU_CTRL), MV_ATUCTL_RESET, 0);
266    if (i < 0) {
267        printk("%s: Timeout waiting for the switch to reset.\n", dev->name);
268        return i;
269    }
270
271    /* set the ATU flags */
272    w16(pdev, MV_SWITCHREG(ATU_CTRL),
273        MV_ATUCTL_NO_LEARN |
274        MV_ATUCTL_ATU_1K |
275        MV_ATUCTL_AGETIME(MV_ATUCTL_AGETIME_MIN) /* minimum without disabling ageing */
276    );
277
278    /* initialize the cpu port */
279    w16(pdev, MV_PORTREG(CONTROL, MV_CPUPORT),
280#ifdef HEADER_MODE
281        MV_PORTCTRL_HEADER |
282#else
283        MV_PORTCTRL_RXTR |
284        MV_PORTCTRL_TXTR |
285#endif
286        MV_PORTCTRL_ENABLED
287    );
288    /* wait for the phy change to settle in */
289    msleep(2);
290    for (i = 0; i < MV_PORTS; i++) {
291        u8 pvid = 0;
292        int j;
293
294        vlmap = 0;
295
296        /* look for the matching vlan */
297        for (j = 0; j < ARRAY_SIZE(priv->vlans); j++) {
298            if (priv->vlans[j] & (1 << i)) {
299                vlmap = priv->vlans[j];
300                pvid = j;
301            }
302        }
303        /* leave port unconfigured if it's not part of a vlan */
304        if (!vlmap)
305            continue;
306
307        /* add the cpu port to the allowed destinations list */
308        vlmap |= (1 << MV_CPUPORT);
309
310        /* take port out of its own vlan destination map */
311        vlmap &= ~(1 << i);
312
313        /* apply vlan settings */
314        w16(pdev, MV_PORTREG(VLANMAP, i),
315            MV_PORTVLAN_PORTS(vlmap) |
316            MV_PORTVLAN_ID(i)
317        );
318
319        /* re-enable port */
320        w16(pdev, MV_PORTREG(CONTROL, i),
321            MV_PORTCTRL_ENABLED
322        );
323    }
324
325    w16(pdev, MV_PORTREG(VLANMAP, MV_CPUPORT),
326        MV_PORTVLAN_ID(MV_CPUPORT)
327    );
328
329    /* set the port association vector */
330    for (i = 0; i <= MV_PORTS; i++) {
331        w16(pdev, MV_PORTREG(ASSOC, i),
332            MV_PORTASSOC_PORTS(1 << i)
333        );
334    }
335
336    /* init switch control */
337    w16(pdev, MV_SWITCHREG(CTRL),
338        MV_SWITCHCTL_MSIZE |
339        MV_SWITCHCTL_DROP
340    );
341
342    /* hook into the tx function */
343    priv->ndo_old = dev->netdev_ops;
344    memcpy(&priv->ndo, priv->ndo_old, sizeof(struct net_device_ops));
345    priv->ndo.ndo_start_xmit = mvswitch_mangle_tx;
346    priv->ndo.ndo_vlan_rx_register = mvswitch_vlan_rx_register;
347    dev->netdev_ops = &priv->ndo;
348
349    pdev->pkt_align = 2;
350    pdev->netif_receive_skb = mvswitch_netif_receive_skb;
351    pdev->netif_rx = mvswitch_netif_rx;
352#ifdef HEADER_MODE
353    dev->features |= NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX;
354#else
355    dev->features |= NETIF_F_HW_VLAN_RX;
356#endif
357
358    return 0;
359}
360
361static int
362mvswitch_read_status(struct phy_device *pdev)
363{
364    pdev->speed = SPEED_100;
365    pdev->duplex = DUPLEX_FULL;
366    pdev->state = PHY_UP;
367
368    /* XXX ugly workaround: we can't force the switch
369     * to gracefully handle hosts moving from one port to another,
370     * so we have to regularly clear the ATU database */
371
372    /* wait for the ATU to become available */
373    mvswitch_wait_mask(pdev, MV_SWITCHREG(ATU_OP), MV_ATUOP_INPROGRESS, 0);
374
375    /* flush the ATU */
376    w16(pdev, MV_SWITCHREG(ATU_OP),
377        MV_ATUOP_INPROGRESS |
378        MV_ATUOP_FLUSH_ALL
379    );
380
381    /* wait for operation to complete */
382    mvswitch_wait_mask(pdev, MV_SWITCHREG(ATU_OP), MV_ATUOP_INPROGRESS, 0);
383
384    return 0;
385}
386
387static int
388mvswitch_config_aneg(struct phy_device *phydev)
389{
390    return 0;
391}
392
393static void
394mvswitch_remove(struct phy_device *pdev)
395{
396    struct mvswitch_priv *priv = to_mvsw(pdev);
397    struct net_device *dev = pdev->attached_dev;
398
399    /* restore old netdev ops */
400    if (priv->ndo_old && dev)
401        dev->netdev_ops = priv->ndo_old;
402    dev->vlan_rx_register = NULL;
403    dev->vlan_rx_kill_vid = NULL;
404    dev->phy_ptr = NULL;
405    dev->features &= ~NETIF_F_HW_VLAN_RX;
406    kfree(priv);
407}
408
409static int
410mvswitch_probe(struct phy_device *pdev)
411{
412    struct mvswitch_priv *priv;
413
414    priv = kzalloc(sizeof(struct mvswitch_priv), GFP_KERNEL);
415    if (priv == NULL)
416        return -ENOMEM;
417
418    pdev->priv = priv;
419
420    return 0;
421}
422
423static int
424mvswitch_fixup(struct phy_device *dev)
425{
426    u16 reg;
427
428    if (dev->addr != 0x10)
429        return 0;
430
431    reg = dev->bus->read(dev->bus, MV_PORTREG(IDENT, 0)) & MV_IDENT_MASK;
432    if (reg != MV_IDENT_VALUE)
433        return 0;
434
435    dev->phy_id = MVSWITCH_MAGIC;
436    return 0;
437}
438
439
440static struct phy_driver mvswitch_driver = {
441    .name = "Marvell 88E6060",
442    .phy_id = MVSWITCH_MAGIC,
443    .phy_id_mask = 0xffffffff,
444    .features = PHY_BASIC_FEATURES,
445    .probe = &mvswitch_probe,
446    .remove = &mvswitch_remove,
447    .config_init = &mvswitch_config_init,
448    .config_aneg = &mvswitch_config_aneg,
449    .read_status = &mvswitch_read_status,
450    .driver = { .owner = THIS_MODULE,},
451};
452
453static int __init
454mvswitch_init(void)
455{
456    phy_register_fixup_for_id(PHY_ANY_ID, mvswitch_fixup);
457    return phy_driver_register(&mvswitch_driver);
458}
459
460static void __exit
461mvswitch_exit(void)
462{
463    phy_driver_unregister(&mvswitch_driver);
464}
465
466module_init(mvswitch_init);
467module_exit(mvswitch_exit);
target/linux/generic-2.6/files-2.6.31/include/linux/glamo-engine.h
1#ifndef __GLAMO_ENGINE_H
2#define __GLAMO_ENGINE_H
3
4enum glamo_engine {
5    GLAMO_ENGINE_CAPTURE = 0,
6    GLAMO_ENGINE_ISP = 1,
7    GLAMO_ENGINE_JPEG = 2,
8    GLAMO_ENGINE_MPEG_ENC = 3,
9    GLAMO_ENGINE_MPEG_DEC = 4,
10    GLAMO_ENGINE_LCD = 5,
11    GLAMO_ENGINE_CMDQ = 6,
12    GLAMO_ENGINE_2D = 7,
13    GLAMO_ENGINE_3D = 8,
14    GLAMO_ENGINE_MMC = 9,
15    GLAMO_ENGINE_MICROP0 = 10,
16    GLAMO_ENGINE_RISC = 11,
17    GLAMO_ENGINE_MICROP1_MPEG_ENC = 12,
18    GLAMO_ENGINE_MICROP1_MPEG_DEC = 13,
19#if 0
20    GLAMO_ENGINE_H264_DEC = 14,
21    GLAMO_ENGINE_RISC1 = 15,
22    GLAMO_ENGINE_SPI = 16,
23#endif
24    __NUM_GLAMO_ENGINES
25};
26
27#endif
target/linux/generic-2.6/files-2.6.31/include/linux/glamofb.h
1#ifndef _LINUX_GLAMOFB_H
2#define _LINUX_GLAMOFB_H
3
4#include <linux/fb.h>
5
6#ifdef __KERNEL__
7
8struct glamo_core;
9struct glamofb_handle;
10
11struct glamo_fb_platform_data {
12    int width, height;
13
14    int num_modes;
15    struct fb_videomode *modes;
16
17    struct glamo_core *core;
18};
19
20int glamofb_cmd_mode(struct glamofb_handle *gfb, int on);
21int glamofb_cmd_write(struct glamofb_handle *gfb, u_int16_t val);
22
23#ifdef CONFIG_MFD_GLAMO
24void glamo_lcm_reset(struct platform_device *pdev, int level);
25#else
26#define glamo_lcm_reset(...) do {} while (0)
27#endif
28
29#endif
30
31#define GLAMOFB_ENGINE_ENABLE _IOW('F', 0x1, __u32)
32#define GLAMOFB_ENGINE_DISABLE _IOW('F', 0x2, __u32)
33#define GLAMOFB_ENGINE_RESET _IOW('F', 0x3, __u32)
34
35#endif
target/linux/generic-2.6/files-2.6.31/include/linux/gpio_buttons.h
1/*
2 * Definitions for the GPIO buttons interface driver
3 *
4 * Copyright (C) 2007,2008 Gabor Juhos <juhosg at openwrt.org>
5 *
6 * This file was based on: /include/linux/gpio_keys.h
7 * The original gpio_keys.h seems not to have a license.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 *
13 */
14
15#ifndef _GPIO_BUTTONS_H_
16#define _GPIO_BUTTONS_H_
17
18struct gpio_button {
19    int gpio; /* GPIO line number */
20    int active_low;
21    char *desc; /* button description */
22    int type; /* input event type (EV_KEY, EV_SW) */
23    int code; /* input event code (KEY_*, SW_*) */
24    int count;
25    int threshold; /* count threshold */
26};
27
28struct gpio_buttons_platform_data {
29    struct gpio_button *buttons;
30    int nbuttons; /* number of buttons */
31    int poll_interval; /* polling interval */
32};
33
34#endif /* _GPIO_BUTTONS_H_ */
35
target/linux/generic-2.6/files-2.6.31/include/linux/gpio_dev.h
1#ifndef _GPIODEV_H__
2#define _GPIODEV_H__
3
4#define IOC_GPIODEV_MAGIC 'B'
5#define GPIO_GET _IO(IOC_GPIODEV_MAGIC, 10)
6#define GPIO_SET _IO(IOC_GPIODEV_MAGIC, 11)
7#define GPIO_CLEAR _IO(IOC_GPIODEV_MAGIC, 12)
8#define GPIO_DIR_IN _IO(IOC_GPIODEV_MAGIC, 13)
9#define GPIO_DIR_OUT _IO(IOC_GPIODEV_MAGIC, 14)
10
11#endif

Archive Download the corresponding diff file



interactive