From 65675a1e84c0b33dfffb46d5add02dfa98491d66 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Thu, 18 Dec 2014 13:52:01 -0600 Subject: [PATCH] Freedom KL25Z: Update the CC3000 support to use the current CC300 interfaces. From Alan Carvalho de Assis --- .../freedom-kl25z/src/kl_boardinitialize.c | 6 + configs/freedom-kl25z/src/kl_spi.c | 21 +- configs/freedom-kl25z/src/kl_wifi.c | 345 ++++++++++++++---- 3 files changed, 303 insertions(+), 69 deletions(-) diff --git a/configs/freedom-kl25z/src/kl_boardinitialize.c b/configs/freedom-kl25z/src/kl_boardinitialize.c index 378de8ea4a..77d8202a0b 100644 --- a/configs/freedom-kl25z/src/kl_boardinitialize.c +++ b/configs/freedom-kl25z/src/kl_boardinitialize.c @@ -126,5 +126,11 @@ void board_initialize(void) #if defined(CONFIG_NSH_LIBRARY) && !defined(CONFIG_NSH_ARCHINIT) (void)nsh_archinitialize(); #endif + + /* CC3000 wireless initialization */ + +#ifdef CONFIG_WL_CC3000 + wireless_archinitialize(0); +#endif } #endif diff --git a/configs/freedom-kl25z/src/kl_spi.c b/configs/freedom-kl25z/src/kl_spi.c index 10113bd095..8bd6cadbec 100644 --- a/configs/freedom-kl25z/src/kl_spi.c +++ b/configs/freedom-kl25z/src/kl_spi.c @@ -1,7 +1,7 @@ /**************************************************************************** * configs/freedom-kl25z/src/kl_spi.c * - * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Copyright (C) 2013-2014 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -90,9 +90,17 @@ void weak_function kl_spiinitialize(void) /* Configure SPI0 chip selects */ #ifdef CONFIG_KL_SPI0 +# ifdef CONFIG_ADXL345_SPI kl_configgpio(GPIO_ADXL345_CS); #endif +# ifdef CONFIG_WL_CC3000 + kl_configgpio(GPIO_WIFI_CS); + kl_configgpio(GPIO_WIFI_EN); + kl_configgpio(GPIO_WIFI_INT); +# endif +#endif + /* Configure SPI1 chip selects */ #ifdef CONFIG_KL_SPI1 @@ -159,12 +167,21 @@ void kl_spi0select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, spivdbg("devid: %d CS: %s\n", (int)devid, selected ? "assert" : "de-assert"); +#ifdef CONFIG_ADXL345_SPI if (devid == SPIDEV_GSENSOR) { /* Active low */ kl_gpiowrite(GPIO_ADXL345_CS, !selected); } +#endif + +#if defined(CONFIG_WL_CC3000) + if (devid == SPIDEV_WIRELESS) + { + kl_gpiowrite(GPIO_WIFI_CS, !selected); + } +#endif } #endif @@ -210,7 +227,7 @@ uint8_t kl_spi1status(FAR struct spi_dev_s *dev, enum spi_dev_e devid) * Name: kl_spi[n]cmddata * * Description: - * Some SPI interfaces, particularly with LCDs, and an auxilary 9th data + * Some SPI interfaces, particularly with LCDs, and an auxiliary 9th data * input that determines where the other 8 data bits represent command or * data. These interfaces control that CMD/DATA GPIO output * diff --git a/configs/freedom-kl25z/src/kl_wifi.c b/configs/freedom-kl25z/src/kl_wifi.c index b72d739424..18cb7be7d6 100644 --- a/configs/freedom-kl25z/src/kl_wifi.c +++ b/configs/freedom-kl25z/src/kl_wifi.c @@ -1,10 +1,9 @@ /**************************************************************************** * configs/freedom-kl25z/src/kl_tsi.c * - * Copyright (C) 2013 Alan Carvalho de Assis + * Copyright (C) 2014 Alan Carvalho de Assis * Author: Alan Carvalho de Assis * - * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -48,8 +47,8 @@ #include #include - -#include +#include +#include #include "up_arch.h" #include "kl_gpio.h" @@ -57,104 +56,316 @@ #include "chip/kl_sim.h" #include "freedom-kl25z.h" - /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ +#ifdef CONFIG_WL_CC3000 +#ifndef CONFIG_WIRELESS +# error "Wireless support requires CONFIG_WIRELESS" +#endif + +#ifndef CONFIG_KL_SPI0 +# error "CC3000 Wireless support requires CONFIG_KL_SPI0" +#endif + +#ifndef CC3000_SPI_FREQUENCY +# define CC3000_SPI_FREQUENCY 16000000 +#endif + +#ifndef CC3000_SPIDEV +# define CC3000_SPIDEV 0 +#endif + +#if CC3000_SPIDEV != 0 +# error "CC3000_SPIDEV must be 0" +#endif + +#ifndef CC3000_DEVMINOR +# define CC3000_DEVMINOR 0 +#endif + +#ifndef CONFIG_CC3000_RX_BUFFER_SIZE +# define CONFIG_CC3000_RX_BUFFER_SIZE 132 +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct kl_config_s +{ + struct cc3000_config_s dev; + xcpt_t handler; +}; /**************************************************************************** * Private Function Prototypes ****************************************************************************/ +/* IRQ/GPIO access callbacks. These operations all hidden behind callbacks + * to isolate the CC3000 driver from differences in GPIO interrupt handling + * by varying boards and MCUs. If possible, interrupts should be configured + * on falling edges to detect the Ready Condition At T2: The normal master + * SPI write sequence is SPI_CS low, followed by SPI_IRQ low CC3000 to host, + * indicating that the CC3000 core module is ready to accept data. T2 + * duration is approximately 7 ms. + * + * irq_attach - Attach the CC3000 interrupt handler to the GPIO + * interrupt + * irq_enable - Enable or disable the GPIO interrupt + * irq_clear - Acknowledge/clear any pending GPIO interrupt + * power_enable - Enable or disable Module enable. + * chip_chip_select - The Chip Select + * irq_read - Return the state of the interrupt GPIO input + * probe - Debug support + */ + +static int wl_attach_irq(FAR struct cc3000_config_s *state, xcpt_t handler); +static void wl_enable_irq(FAR struct cc3000_config_s *state, bool enable); +static void wl_clear_irq(FAR struct cc3000_config_s *state); +static void wl_select(FAR struct cc3000_config_s *state, bool enable); +static void wl_enable_power(FAR struct cc3000_config_s *state, bool enable); +static bool wl_read_irq(FAR struct cc3000_config_s *state); +#ifdef CONFIG_CC3000_PROBES +static bool probe(FAR struct cc3000_config_s *state,int n, bool s); +#endif /**************************************************************************** * Private Data ****************************************************************************/ +/* A reference to a structure of this type must be passed to the CC3000 + * driver. This structure provides information about the configuration + * of the CC3000 and provides some board-specific hooks. + * + * Memory for this structure is provided by the caller. It is not copied + * by the driver and is presumed to persist while the driver is active. The + * memory must be writable because, under certain circumstances, the driver + * may modify frequency or X plate resistance values. + */ + +static struct kl_config_s g_cc3000_info = +{ + .dev.spi_frequency = CONFIG_CC3000_SPI_FREQUENCY, + .dev.spi_mode = CONFIG_CC3000_SPI_MODE, + .dev.max_rx_size = 0, + .dev.irq_attach = wl_attach_irq, + .dev.irq_enable = wl_enable_irq, + .dev.irq_clear = wl_clear_irq, + .dev.power_enable = wl_enable_power, + .dev.chip_chip_select = wl_select, + .dev.irq_read = wl_read_irq, +#ifdef CONFIG_CC3000_PROBES + .dev.probe = probe, /* This is used for debugging */ +#endif + .handler = NULL, +}; /**************************************************************************** * Private Functions ****************************************************************************/ +/* IRQ/GPIO access callbacks. These operations all hidden behind + * callbacks to isolate the CC3000 driver from differences in GPIO + * interrupt handling by varying boards and MCUs. If possible, + * interrupts should be configured on both rising and falling edges + * so that contact and loss-of-contact events can be detected. + * + * irq_attach - Attach the CC3000 interrupt handler to the GPIO + * interrupt + * irq_enable - Enable or disable the GPIO interrupt + * irq_clear - Acknowledge/clear any pending GPIO interrupt + * power_enable - Enable or disable Module enable. + * chip_chip_select - The Chip Select + * irq_read - Return the state of the interrupt GPIO input + * probe - Debug support + */ + +static int wl_attach_irq(FAR struct cc3000_config_s *state, xcpt_t handler) +{ + FAR struct kl_config_s *priv = (FAR struct kl_config_s *)state; + + /* Just save the handler for use when the interrupt is enabled */ + + priv->handler = handler; + return OK; +} + +static void wl_enable_irq(FAR struct cc3000_config_s *state, bool enable) +{ + FAR struct kl_config_s *priv = (FAR struct kl_config_s *)state; + + /* The caller should not attempt to enable interrupts if the handler + * has not yet been 'attached' + */ + + DEBUGASSERT(priv->handler || !enable); + + /* Attach and enable, or detach and disable */ + + ivdbg("enable:%d\n", enable); + if (enable) + { + (void)kl_gpioirqattach(GPIO_WIFI_INT, priv->handler); + kl_gpioirqenable(GPIO_WIFI_INT); + } + else + { + (void)kl_gpioirqattach(GPIO_WIFI_INT, NULL); + kl_gpioirqdisable(GPIO_WIFI_INT); + } +} + +static void wl_enable_power(FAR struct cc3000_config_s *state, bool enable) +{ + ivdbg("enable:%d\n", enable); + + /* Active high enable */ + + kl_gpiowrite(GPIO_WIFI_EN, enable); +} + +static void wl_select(FAR struct cc3000_config_s *state, bool enable) +{ + ivdbg("enable:%d\n", enable); + + /* Active high enable */ + + kl_gpiowrite(GPIO_WIFI_CS, enable); +} + +static void wl_clear_irq(FAR struct cc3000_config_s *state) +{ + /* Does nothing */ +} + +static bool wl_read_irq(FAR struct cc3000_config_s *state) +{ + /* Active low*/ + + return kl_gpioread(GPIO_WIFI_INT) ? false : true; +} + +#ifdef CONFIG_CC3000_PROBES +static bool probe(FAR struct cc3000_config_s *state,int n, bool s) +{ + if (n == 0) + { + kl_gpiowrite(GPIO_D0, s); + } + + if (n == 1) + { + kl_gpiowrite(GPIO_D1, s); + } + + return true; +} +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ -/* Used by CC3000 driver to read status of WIFI_IRQ */ - -inline long ReadWlanInterruptPin(void) -{ - /* Return the status of WIFI_IRQ pin */ - - return kl_gpioread(GPIO_WIFI_IRQ); -} - -/* Enable/Disable WiFi */ - -void WriteWlanEnablePin(uint8_t val) -{ - kl_gpiowrite(GPIO_WIFI_EN, val); -} - -/* Assert CC3000 CS */ - -void AssertWlanCS(void) -{ - kl_gpiowrite(GPIO_WIFI_CS, false); -} - -/* Deassert CC3000 CS */ - -void DeassertWlanCS(void) -{ - kl_gpiowrite(GPIO_WIFI_CS, true); -} - /**************************************************************************** - * Name: Wlan_Setup + * Name: arch_wlinitialize * * Description: - * Initialize all pins needed to control CC3000 Module and attach to IRQ + * Each board that supports a wireless device must provide this function. + * This function is called by application-specific, setup logic to + * configure the wireless device. This function will register the driver + * as /dev/wirelessN where N is the minor device number. + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. * ****************************************************************************/ -void Wlan_Setup(void) +int wireless_archinitialize(size_t max_rx_size) { - int ret; - uint32_t regval; + FAR struct spi_dev_s *spi; - printf("\nExecuting kl_irq_initialize!\n"); + /* Init SPI bus */ - /* Configure the PIN used to enable the chip */ + idbg("minor %d\n", minor); + DEBUGASSERT(CONFIG_CC3000_DEVMINOR == 0); - kl_configgpio(GPIO_WIFI_EN); +#ifdef CONFIG_CC3000_PROBES + kl_configgpio(GPIO_D0); + kl_configgpio(GPIO_D1); + kl_gpiowrite(GPIO_D0, 1); + kl_gpiowrite(GPIO_D1, 1); +#endif - /* Configure PIN to detect interrupts */ + /* Get an instance of the SPI interface */ - kl_configgpio(GPIO_WIFI_IRQ); - - /* Configure PIN used as SPI CS */ - - kl_configgpio(GPIO_WIFI_CS); - - /* Make sure the chip is OFF before we start */ - - WriteWlanEnablePin(false); - - /* Make sure the SPI CS pin is deasserted */ - - DeassertWlanCS(); - - /* Configure pin to detect interrupt on falling edge */ - - regval = getreg32(KL_PORTA_PCR16); - regval |= PORT_PCR_IRQC_FALLING; - putreg32(regval, KL_PORTA_PCR16); - - ret = irq_attach(KL_IRQ_PORTA, CC3000InterruptHandler); - if (ret == OK) + spi = up_spiinitialize(CONFIG_CC3000_SPIDEV); + if (!spi) { - up_enable_irq(KL_IRQ_PORTA); + idbg("Failed to initialize SPI bus %d\n", CONFIG_CC3000_SPIDEV); + return -ENODEV; } + + /* Initialize and register the SPI CC3000 device */ + + g_cc3000_info.dev.max_rx_size = max_rx_size ? max_rx_size : CONFIG_CC3000_RX_BUFFER_SIZE; + int ret = cc3000_register(spi, &g_cc3000_info.dev, CONFIG_CC3000_DEVMINOR); + if (ret < 0) + { + idbg("Failed to initialize SPI bus %d\n", CONFIG_CC3000_SPIDEV); + return -ENODEV; + } + + return OK; } + +/***************************************************************************** + * Name: C3000_wlan_init + * + * Description: + * Initialize wlan driver + * + * Warning: This function must be called before ANY other wlan driver + * function + * + * Input Parmeters: + * sWlanCB Asynchronous events callback. + * 0 no event call back. + * - Call back parameters: + * 1) event_type: HCI_EVNT_WLAN_UNSOL_CONNECT connect event, + * HCI_EVNT_WLAN_UNSOL_DISCONNECT disconnect event, + * HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE config done, + * HCI_EVNT_WLAN_UNSOL_DHCP dhcp report, + * HCI_EVNT_WLAN_ASYNC_PING_REPORT ping report OR + * HCI_EVNT_WLAN_KEEPALIVE keepalive. + * 2) data: pointer to extra data that received by the event + * (NULL no data). + * 3) length: data length. + * - Events with extra data: + * HCI_EVNT_WLAN_UNSOL_DHCP: 4 bytes IP, 4 bytes Mask, + * 4 bytes default gateway, 4 bytes DHCP server and 4 bytes + * for DNS server. + * HCI_EVNT_WLAN_ASYNC_PING_REPORT: 4 bytes Packets sent, + * 4 bytes Packets received, 4 bytes Min round time, + * 4 bytes Max round time and 4 bytes for Avg round time. + * + * sFWPatches 0 no patch or pointer to FW patches + * sDriverPatches 0 no patch or pointer to driver patches + * sBootLoaderPatches 0 no patch or pointer to bootloader patches + * + * Returned Value: + * None + * + ****************************************************************************/ + +void cc3000_wlan_init(size_t max_tx_len, + tWlanCB sWlanCB, + tFWPatches sFWPatches, tDriverPatches + sDriverPatches, tBootLoaderPatches sBootLoaderPatches) +{ + wlan_init(max_tx_len, sWlanCB, sFWPatches, sDriverPatches, sBootLoaderPatches); +} + +#endif /* CONFIG_WL_CC3000 */