Hi Pieter, On Wed, May 09, 2012 at 08:41:41AM +0200, Pieter Voorthuijsen wrote: > 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> > --- > > Index: target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-netgear.c > =================================================================== > --- target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-netgear.c > (revision 31548) > +++ target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-netgear.c > (working copy) > @@ -4,6 +4,7 @@ > * by the Free Software Foundation. > * > * Copyright (C) 2010 John Crispin <blo...@openwrt.org> > + * Copyright (C) 2012 Pieter Voorthuijsen > */ > > #include <linux/init.h> > @@ -15,14 +16,31 @@ > #include <linux/phy.h> > #include <linux/spi/spi.h> > #include <linux/spi/flash.h> > +#include <linux/spi/spi_gpio.h> > +#include <linux/ath9k_platform.h> > +#include <linux/if_ether.h> > +#include <linux/etherdevice.h> > +#include <linux/kobject.h> > +#include <linux/sysfs.h> > > #include <lantiq_soc.h> > #include <irq.h> > +#include <dev-gpio-leds.h> > +#include <dev-gpio-buttons.h> > +#include "dev-wifi-athxk.h" > > #include "../machtypes.h" > #include "devices.h" > #include "dev-dwc_otg.h" > +#include "pci-ath-fixup.h" > +#include <mtd/mtd-abi.h> > +#include <asm-generic/sizes.h> > > +#define SPI_GPIO_MRST 16 > +#define SPI_GPIO_MTSR 17 > +#define SPI_GPIO_CLK 18 > +#define SPI_GPIO_CS0 10 > + > static struct ltq_pci_data ltq_pci_data = { > .clock = PCI_CLOCK_INT, > .gpio = PCI_GNT1 | PCI_REQ1, > @@ -35,49 +53,221 @@ > .mii_mode = PHY_INTERFACE_MODE_MII, > }; > > -static struct mtd_partition easy98000_nor_partitions[] = > -{
Usually partition information is on top... > +static struct gpio_led > +dgn3500_gpio_leds[] __initdata = { > + { .name = "soc:green:power", .gpio = 34, .active_low = 1, }, > + { .name = "soc:red:power", .gpio = 39, .active_low = 1, }, > + /* Green WLAN can be controlled via ath or alt setting ?? */ > + /*{ .name = "soc:green:wlan", .gpio = 10, .active_low = 1, }, */ > + { .name = "soc:orange:wlan", .gpio = 51, .active_low = 1, }, > + { .name = "soc:green:wps", .gpio = 52, .active_low = 1, }, > + { .name = "soc:green:usb", .gpio = 22, .active_low = 1, }, > + { .name = "soc:green:dsl", .gpio = 4, .active_low = 1, }, > + { .name = "soc:green:internet", .gpio = 2, .active_low = 1, }, > + /* Red internet is in use by PCI GNT1 signal?? */ > + /*{ .name = "soc:red:internet", .gpio = 30, .active_low = 1, }*/ > +}; > + > +static struct gpio_keys_button > +dgn3500_gpio_keys[] __initdata = { > { > - .name = "uboot", > - .offset = 0x0, > - .size = 0x40000, > + .desc = "wps", > + .type = EV_KEY, > + .code = BTN_0, > + .debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL, > + .gpio = 54, > + .active_low = 1, > }, > { > - .name = "uboot_env", > - .offset = 0x40000, > - .size = 0x40000, /* 2 sectors for redundant env. */ > + .desc = "reset", > + .type = EV_KEY, > + .code = BTN_1, > + .debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL, > + .gpio = 36, > + .active_low = 1, > }, > +}; > + > +static struct mtd_partition dgn3500_partitions[] = { > { > - .name = "linux", > - .offset = 0x80000, > - .size = 0xF80000, /* map only 16 MiB */ > + .name = "u-boot", > + .offset = 0, > + .size = SZ_64K, I prefer the old way of defining this. If we are going to use this we should change all lantiq targets. > + .mask_flags = MTD_WRITEABLE, I think we do not need to define this. > }, > + { > + .name = "environment", > + .offset = MTDPART_OFS_APPEND, > + .size = SZ_64K, > + .mask_flags = MTD_WRITEABLE, > + }, > + { > + .name = "dpf", Can you tell us why we need this partition? > + .offset = MTDPART_OFS_APPEND, > + .size = SZ_64K, > + .mask_flags = MTD_WRITEABLE, > + }, > + { > + .name = "nvram", Can you tell us why we need this partition? > + .offset = MTDPART_OFS_APPEND, > + .size = SZ_128K, > + .mask_flags = MTD_WRITEABLE, > + }, > + { > + .name = "linux", > + .offset = MTDPART_OFS_APPEND, > + .size = SZ_1K * 12800, > + }, > + { > + .name = "uilang", Can you tell us why we need this partition? > + .offset = MTDPART_OFS_APPEND, > + .size = SZ_1M * 3, > + }, > + { > + .name = "tm", Can you tell us why we need this partition? > + .offset = MTDPART_OFS_APPEND, > + .size = SZ_128K, > + .mask_flags = MTD_WRITEABLE, > + }, > + { > + .name = "pot", Can you tell us why we need this partition? > + .offset = MTDPART_OFS_APPEND, > + .size = SZ_64K, > + .mask_flags = MTD_WRITEABLE, > + }, > + { > + .name = "entire_flash", No need for this. > + .offset = 0, > + .size = SZ_16M, > + .mask_flags = MTD_WRITEABLE, > + }, > }; > > -static struct flash_platform_data easy98000_spi_flash_platform_data = { > - .name = "sflash", > - .parts = easy98000_nor_partitions, > - .nr_parts = ARRAY_SIZE(easy98000_nor_partitions) > +static struct spi_gpio_platform_data spi_gpio_data = { > + .sck = SPI_GPIO_CLK, > + .mosi = SPI_GPIO_MTSR, > + .miso = SPI_GPIO_MRST, > + .num_chipselect = 2, > }; > > -static struct spi_board_info spi_info __initdata = { > - .modalias = "m25p80", > - .bus_num = 0, > - .chip_select = 3, > - .max_speed_hz = 10 * 1000 * 1000, > - .mode = SPI_MODE_3, > - .platform_data = &easy98000_spi_flash_platform_data > +static struct platform_device spi_gpio_device = { > + .name = "spi_gpio", > + .dev.platform_data = &spi_gpio_data, > }; > > -struct ltq_spi_platform_data ltq_spi_data = { > - .num_chipselect = 4, > +static struct flash_platform_data spi_flash_data = { > + .name = "sflash", > + .parts = dgn3500_partitions, > + .nr_parts = ARRAY_SIZE(dgn3500_partitions), > }; > > +static struct spi_board_info spi_flash __initdata = { > + .modalias = "m25p80", > + .bus_num = 0, > + .chip_select = 0, > + .max_speed_hz = 10 * 1000 * 1000, > + .mode = SPI_MODE_3, > + .chip_select = 0, > + .controller_data = (void *) SPI_GPIO_CS0, > + .platform_data = &spi_flash_data > +}; > + > +static u8 ltq_ethaddr[6] = { 0 }; > + > +static int __init setup_ethaddr(char *str) > +{ > + if (!mac_pton(str, ltq_ethaddr)) > + memset(ltq_ethaddr, 0, 6); What if mac address is not passed to kernel when booting? > + return 0; > +} > +__setup("ethaddr=", setup_ethaddr); > + > +static u16 dgn3500_eeprom_data[ATH9K_PLAT_EEP_MAX_WORDS] = {0}; > + > +static ssize_t ath_eeprom_read(struct file *filp, struct kobject *kobj, > + struct bin_attribute *attr, char *buf, > + loff_t offset, size_t count) > +{ > + if (unlikely(offset >= sizeof(dgn3500_eeprom_data))) > + return 0; > + if ((offset + count) > sizeof(dgn3500_eeprom_data)) > + count = sizeof(dgn3500_eeprom_data) - offset; > + if (unlikely(!count)) > + return count; > + > + memcpy(buf, (char *)(dgn3500_eeprom_data) + offset, count); > + > + return count; > +} > + > +extern struct ath9k_platform_data ath9k_pdata; > + > +static ssize_t ath_eeprom_write(struct file *filp, struct kobject *kobj, > + struct bin_attribute *attr, char *buf, > + loff_t offset, size_t count) > +{ > + int i; > + char *eeprom_bytes = (char *)dgn3500_eeprom_data; > + > + if (unlikely(offset >= sizeof(dgn3500_eeprom_data))) > + return -EFBIG; > + if ((offset + count) > sizeof(dgn3500_eeprom_data)) > + count = sizeof(dgn3500_eeprom_data) - offset; > + if (unlikely(!count)) > + return count; > + if (count % 2) > + return 0; > + > + /* The PCI fixup routine requires an endian swap of the calibartion data > + * stored in flash */ > + for (i = 0; i < count; i += 2) { > + eeprom_bytes[offset + i + 1] = buf[i]; > + eeprom_bytes[offset + i] = buf[i+1]; > + } > + > + /* The original data does not contain a checksum. Set the country and > + * calculate new checksum when all data is received */ > + if ((count + offset) == sizeof(dgn3500_eeprom_data)) > + memcpy(ath9k_pdata.eeprom_data, dgn3500_eeprom_data, > + sizeof(ath9k_pdata.eeprom_data)); > + > + return count; > +} > + > +static struct bin_attribute dev_attr_ath_eeprom = { > + .attr = { > + .name = "ath_eeprom", > + .mode = S_IRUGO|S_IWUSR, > + }, > + .read = ath_eeprom_read, > + .write = ath_eeprom_write, > +}; > + > static void __init dgn3500_init(void) > { > + if (!sysfs_create_bin_file(firmware_kobj, &dev_attr_ath_eeprom)) > + printk(KERN_INFO "failed to create sysfs entry firm ath > eeprom\n"); > + > + ltq_add_device_gpio_leds(-1, ARRAY_SIZE(dgn3500_gpio_leds), > + dgn3500_gpio_leds); > + ltq_register_gpio_keys_polled(-1, LTQ_KEYS_POLL_INTERVAL, > + ARRAY_SIZE(dgn3500_gpio_keys), dgn3500_gpio_keys); > + > + platform_device_register(&spi_gpio_device); > + > ltq_register_pci(<q_pci_data); > + spi_register_board_info(&spi_flash, 1); > + > + if (!is_valid_ether_addr(ltq_ethaddr)) { > + printk(KERN_INFO "mac address not present or invalid,"\ > + "using random\n"); > + random_ether_addr(ltq_ethaddr); > + } > + memcpy(<q_eth_data.mac.sa_data, ltq_ethaddr, 6); > ltq_register_etop(<q_eth_data); > - ltq_register_spi(<q_spi_data, &spi_info, 1); > + ltq_register_ath9k(dgn3500_eeprom_data, ltq_ethaddr); > + ltq_pci_ath_fixup(14, dgn3500_eeprom_data); > + > /* The usb power is always enabled, protected by a fuse */ > xway_register_dwc(-1); > } > Index: target/linux/lantiq/config-3.2 > =================================================================== > --- target/linux/lantiq/config-3.2 (revision 31548) > +++ target/linux/lantiq/config-3.2 (working copy) > @@ -57,6 +57,9 @@ > CONFIG_HAVE_IRQ_WORK=y > CONFIG_HAVE_OPROFILE=y > CONFIG_HAVE_PERF_EVENTS=y > +CONFIG_HOTPLUG_PCI=y > +CONFIG_HOTPLUG_PCI_FAKE=y > +CONFIG_HW_HAS_PCI=y > CONFIG_HW_RANDOM=y > CONFIG_HZ=250 > # CONFIG_HZ_100 is not set > @@ -83,11 +86,15 @@ > CONFIG_MTD_CFI_ADV_OPTIONS=y > CONFIG_MTD_CFI_GEOMETRY=y > CONFIG_MTD_CMDLINE_PARTS=y > +CONFIG_MTD_M25P80=y > CONFIG_MTD_LANTIQ=y > CONFIG_MTD_UIMAGE_SPLIT=y > CONFIG_NEED_DMA_MAP_STATE=y > CONFIG_NEED_PER_CPU_KM=y > CONFIG_PAGEFLAGS_EXTENDED=y > +CONFIG_PCI=y > +CONFIG_PCI_DOMAINS=y > +CONFIG_PCI_LANTIQ_NONE=y > CONFIG_PERF_USE_VMALLOC=y > CONFIG_PHYLIB=y > # CONFIG_PREEMPT_RCU is not set > @@ -99,6 +106,11 @@ > CONFIG_SERIAL_LANTIQ=y > CONFIG_SWAP_IO_SPACE=y > CONFIG_SWCONFIG=y > +CONFIG_SPI=y > +CONFIG_SPI_BITBANG=y > +CONFIG_SPI_GPIO=y > +CONFIG_SPI_MASTER=y > +CONFIG_SWAP_IO_SPACE=y > CONFIG_SYS_HAS_CPU_MIPS32_R1=y > CONFIG_SYS_HAS_CPU_MIPS32_R2=y > CONFIG_SYS_HAS_EARLY_PRINTK=y > Index: target/linux/lantiq/base-files/lib/preinit/42_athfix > =================================================================== > --- target/linux/lantiq/base-files/lib/preinit/42_athfix (revision 0) > +++ target/linux/lantiq/base-files/lib/preinit/42_athfix (revision 0) > @@ -0,0 +1,19 @@ > +#!/bin/sh > + > +. /lib/lantiq.sh > + > +init_atheeprom() { > + local board=$(lantiq_board_name) > + case $board in > + "Netgear DGN3500B") > + echo "- loading eeprom -" > + dd if=/dev/mtd2 of=/sys/firmware/ath_eeprom bs=1k skip=60 > count=4 > + echo 0 > /sys/bus/pci/slots/0000\:00\:0e.0/power > + sleep 1 > + echo 1 > /sys/bus/pci/rescan > + ;; > + esac > +} > + > +boot_hook_add preinit_essential init_atheeprom Regards, Luka _______________________________________________ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/mailman/listinfo/openwrt-devel