Changeset 31910


Ignore:
Timestamp:
2012-05-27T18:02:22+02:00 (6 years ago)
Author:
blogic
Message:

[lantiq] dgn3500 support with eeprom loading from sysfs

WIFI eeprom:
As discussed, it is impossible for nand and spi flash platforms to have the eeprom data available from mtd. I suggested to load the eeprom from user-space. I've looked into regular firmware loading but this is only possible when using modules. I've created a sysfs entry that allows reading and writing the eeprom data to the platform data. After loading the eeprom data I rely on pci-hotplug support to disable the bogus pci device and rescan the bus (with fixups and all). Because hotplug is not available, an init script is created that performs the copy from mtd to platform data. I think it is best to eventually move the sysfs functions to dev_wifi_athxk.c file, this would get rid of the external to the ath9k platform data.

SPI flash:
It seems that the spi-xway driver is not really working. It causes my kernel to crash in all sorts of ways. I added to bitbang SPI to be able to the calibration data mention above.
I've kept the original mtd partitioning that Netgear uses.

Buttons/LED:
Both buttons are working properly. Two leds are not enabled: The red internet led is connected to the pci_gnt1 pin... I can't disable it because then DMA stops working.
The green wifi led is connected to an unknown atheros gpio.

Signed-off-by: Pieter Voorthuijsen <p.voorthuijsen at gmail.com>

Location:
trunk/target/linux/lantiq
Files:
2 added
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/target/linux/lantiq/files-3.3/arch/mips/lantiq/xway/mach-netgear.c

    r31307 r31910  
    55 * 
    66 *  Copyright (C) 2010 John Crispin <blogic@openwrt.org> 
     7 *  Copyright (C) 2012 Pieter Voorthuijsen <p.voorthuijsen@gmail.com> 
    78 */ 
    89 
     
    1617#include <linux/spi/spi.h> 
    1718#include <linux/spi/flash.h> 
     19#include <linux/spi/spi_gpio.h> 
     20#include <linux/ath9k_platform.h> 
     21#include <linux/if_ether.h> 
     22#include <linux/etherdevice.h> 
     23#include <linux/kobject.h> 
     24#include <linux/sysfs.h> 
    1825 
    1926#include <lantiq_soc.h> 
    2027#include <irq.h> 
     28#include <dev-gpio-leds.h> 
     29#include <dev-gpio-buttons.h> 
     30#include "dev-wifi-athxk.h" 
    2131 
    2232#include "../machtypes.h" 
    2333#include "devices.h" 
    2434#include "dev-dwc_otg.h" 
     35#include "pci-ath-fixup.h" 
     36#include <mtd/mtd-abi.h> 
     37#include <asm-generic/sizes.h> 
     38 
     39static struct mtd_partition dgn3500_partitions[] = { 
     40        { 
     41                .name = "u-boot", 
     42                .offset = 0, 
     43                .size = 0x10000, 
     44                .mask_flags = MTD_WRITEABLE, 
     45        }, 
     46        { 
     47                .name = "environment", 
     48                .offset = 0x10000, 
     49                .size = 0x10000, 
     50                .mask_flags = MTD_WRITEABLE, 
     51        }, 
     52        { 
     53                .name = "calibration", 
     54                .offset = 0x20000, 
     55                .size = 0x10000, 
     56                .mask_flags = MTD_WRITEABLE, 
     57        }, 
     58        { 
     59                .name = "linux", 
     60                .offset = 0x50000, 
     61                .size = 0xfa0000, 
     62        }, 
     63}; 
    2564 
    2665static struct ltq_pci_data ltq_pci_data = { 
     
    3675}; 
    3776 
    38 static struct mtd_partition easy98000_nor_partitions[] = 
    39 { 
    40         { 
    41                 .name   = "uboot", 
    42                 .offset = 0x0, 
    43                 .size   = 0x40000, 
    44         }, 
    45         { 
    46                 .name   = "uboot_env", 
    47                 .offset = 0x40000, 
    48                 .size   = 0x40000,      /* 2 sectors for redundant env. */ 
    49         }, 
    50         { 
    51                 .name   = "linux", 
    52                 .offset = 0x80000, 
    53                 .size   = 0xF80000,     /* map only 16 MiB */ 
    54         }, 
    55 }; 
    56  
    57 static struct flash_platform_data easy98000_spi_flash_platform_data = { 
    58         .name = "sflash", 
    59         .parts = easy98000_nor_partitions, 
    60         .nr_parts = ARRAY_SIZE(easy98000_nor_partitions) 
    61 }; 
    62  
    63 static struct spi_board_info spi_info __initdata = { 
    64         .modalias               = "m25p80", 
    65         .bus_num                = 0, 
    66         .chip_select            = 3, 
    67         .max_speed_hz           = 10 * 1000 * 1000, 
    68         .mode                   = SPI_MODE_3, 
    69         .platform_data          = &easy98000_spi_flash_platform_data 
    70 }; 
    71  
    72 struct ltq_spi_platform_data ltq_spi_data = { 
    73         .num_chipselect = 4, 
     77static struct gpio_led 
     78dgn3500_gpio_leds[] __initdata = { 
     79        { .name = "soc:green:power", .gpio = 34, .active_low = 1, }, 
     80        { .name = "soc:red:power", .gpio = 39, .active_low = 1, }, 
     81        { .name = "soc:orange:wlan", .gpio = 51, .active_low = 1, }, 
     82        { .name = "soc:green:wps", .gpio = 52, .active_low = 1, }, 
     83        { .name = "soc:green:usb", .gpio = 22, .active_low = 1, }, 
     84        { .name = "soc:green:dsl", .gpio = 4, .active_low = 1, }, 
     85        { .name = "soc:green:internet", .gpio = 2, .active_low = 1, }, 
     86}; 
     87 
     88static struct gpio_keys_button 
     89dgn3500_gpio_keys[] __initdata = { 
     90        { 
     91                .desc = "wps", 
     92                .type = EV_KEY, 
     93                .code = BTN_0, 
     94                .debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL, 
     95                .gpio = 54, 
     96                .active_low = 1, 
     97        }, 
     98        { 
     99                .desc = "reset", 
     100                .type = EV_KEY, 
     101                .code = BTN_1, 
     102                .debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL, 
     103                .gpio = 36, 
     104                .active_low = 1, 
     105        }, 
     106}; 
     107 
     108#define SPI_GPIO_MRST   16 
     109#define SPI_GPIO_MTSR   17 
     110#define SPI_GPIO_CLK    18 
     111#define SPI_GPIO_CS0    10 
     112 
     113static struct spi_gpio_platform_data spi_gpio_data = { 
     114        .sck            = SPI_GPIO_CLK, 
     115        .mosi           = SPI_GPIO_MTSR, 
     116        .miso           = SPI_GPIO_MRST, 
     117        .num_chipselect = 2, 
     118}; 
     119 
     120static struct platform_device spi_gpio_device = { 
     121        .name                   = "spi_gpio", 
     122        .dev.platform_data      = &spi_gpio_data, 
     123}; 
     124 
     125static struct flash_platform_data spi_flash_data = { 
     126        .name           = "sflash", 
     127        .parts          = dgn3500_partitions, 
     128        .nr_parts       = ARRAY_SIZE(dgn3500_partitions), 
     129}; 
     130 
     131static struct spi_board_info spi_flash __initdata = { 
     132        .modalias               = "m25p80", 
     133        .bus_num                = 0, 
     134        .chip_select            = 0, 
     135        .max_speed_hz           = 10 * 1000 * 1000, 
     136        .mode                   = SPI_MODE_3, 
     137        .chip_select            = 0, 
     138        .controller_data        = (void *) SPI_GPIO_CS0, 
     139        .platform_data          = &spi_flash_data 
     140}; 
     141 
     142static u8 ltq_ethaddr[6] = { 0 }; 
     143 
     144static int __init setup_ethaddr(char *str) 
     145{ 
     146        if (!mac_pton(str, ltq_ethaddr)) 
     147                memset(ltq_ethaddr, 0, 6); 
     148        return 0; 
     149} 
     150__setup("ethaddr=", setup_ethaddr); 
     151 
     152static u16 dgn3500_eeprom_data[ATH9K_PLAT_EEP_MAX_WORDS] = {0}; 
     153 
     154static ssize_t ath_eeprom_read(struct file *filp, struct kobject *kobj, 
     155                struct bin_attribute *attr, char *buf, 
     156                loff_t offset, size_t count) 
     157{ 
     158        if (unlikely(offset >= sizeof(dgn3500_eeprom_data))) 
     159                return 0; 
     160        if ((offset + count) > sizeof(dgn3500_eeprom_data)) 
     161                count = sizeof(dgn3500_eeprom_data) - offset; 
     162        if (unlikely(!count)) 
     163                return count; 
     164 
     165        memcpy(buf, (char *)(dgn3500_eeprom_data) + offset, count); 
     166 
     167        return count; 
     168} 
     169 
     170extern struct ath9k_platform_data ath9k_pdata; 
     171 
     172static ssize_t ath_eeprom_write(struct file *filp, struct kobject *kobj, 
     173                struct bin_attribute *attr, char *buf, 
     174                loff_t offset, size_t count) 
     175{ 
     176        int i; 
     177        char *eeprom_bytes = (char *)dgn3500_eeprom_data; 
     178 
     179        if (unlikely(offset >= sizeof(dgn3500_eeprom_data))) 
     180                return -EFBIG; 
     181        if ((offset + count) > sizeof(dgn3500_eeprom_data)) 
     182                count = sizeof(dgn3500_eeprom_data) - offset; 
     183        if (unlikely(!count)) 
     184                return count; 
     185        if (count % 2) 
     186                return 0; 
     187 
     188        /* The PCI fixup routine requires an endian swap of the calibartion data 
     189         * stored in flash */ 
     190        for (i = 0; i < count; i += 2) { 
     191                eeprom_bytes[offset + i + 1] = buf[i]; 
     192                eeprom_bytes[offset + i] = buf[i+1]; 
     193        } 
     194 
     195        /* The original data does not contain a checksum. Set the country and 
     196         * calculate new checksum when all data is received */ 
     197        if ((count + offset) == sizeof(dgn3500_eeprom_data)) 
     198                memcpy(ath9k_pdata.eeprom_data, dgn3500_eeprom_data, 
     199                                sizeof(ath9k_pdata.eeprom_data)); 
     200 
     201        return count; 
     202} 
     203 
     204static struct bin_attribute dev_attr_ath_eeprom = { 
     205        .attr = { 
     206                .name = "ath_eeprom", 
     207                .mode = S_IRUGO|S_IWUSR, 
     208        }, 
     209        .read = ath_eeprom_read, 
     210        .write = ath_eeprom_write, 
    74211}; 
    75212 
    76213static void __init dgn3500_init(void) 
    77214{ 
     215        if (sysfs_create_bin_file(firmware_kobj, &dev_attr_ath_eeprom)) 
     216                printk(KERN_INFO "Failed to create ath eeprom sysfs entry\n"); 
     217        ltq_add_device_gpio_leds(-1, ARRAY_SIZE(dgn3500_gpio_leds), 
     218                        dgn3500_gpio_leds); 
     219        ltq_register_gpio_keys_polled(-1, LTQ_KEYS_POLL_INTERVAL, 
     220                        ARRAY_SIZE(dgn3500_gpio_keys), dgn3500_gpio_keys); 
     221        platform_device_register(&spi_gpio_device); 
    78222        ltq_register_pci(&ltq_pci_data); 
     223        spi_register_board_info(&spi_flash, 1); 
     224        if (!is_valid_ether_addr(ltq_ethaddr)) { 
     225                printk(KERN_INFO "MAC invalid using random\n"); 
     226                random_ether_addr(ltq_ethaddr); 
     227        } 
     228        memcpy(&ltq_eth_data.mac.sa_data, ltq_ethaddr, 6); 
    79229        ltq_register_etop(&ltq_eth_data); 
    80         ltq_register_spi(&ltq_spi_data, &spi_info, 1); 
     230        ltq_register_ath9k(dgn3500_eeprom_data, ltq_ethaddr); 
     231        ltq_pci_ath_fixup(14, dgn3500_eeprom_data); 
    81232        /* The usb power is always enabled, protected by a fuse */ 
    82233        xway_register_dwc(-1); 
Note: See TracChangeset for help on using the changeset viewer.