2019-05-23 12:14:39 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2009-10-04 16:55:28 +04:00
/*
2012-09-14 20:25:00 +04:00
* DBAu1000 / 1500 / 1100 PBAu1100 / 1500 board support
2009-10-04 16:55:28 +04:00
*
2011-11-10 16:06:21 +04:00
* Copyright 2000 , 2008 MontaVista Software Inc .
* Author : MontaVista Software , Inc . < source @ mvista . com >
2009-10-04 16:55:28 +04:00
*/
2014-07-23 18:36:54 +04:00
# include <linux/clk.h>
2011-11-10 16:06:21 +04:00
# include <linux/dma-mapping.h>
# include <linux/gpio.h>
spi: spi-gpio: Rewrite to use GPIO descriptors
This converts the bit-banged GPIO SPI driver to looking up and
using GPIO descriptors to get a handle on GPIO lines for SCK,
MOSI, MISO and all CS lines.
All existing board files are converted in one go to keep it all
consistent. With these conversions I rarely find any interrim
steps that makes any sense.
Device tree probing and GPIO handling should work like before
also after this patch.
For board files, we stop using controller data to pass the GPIO
line for chip select, instead we pass this as a GPIO descriptor
lookup like everything else.
In some s3c24xx machines the names of the SPI devices were set to
"spi-gpio" rather than "spi_gpio" which can never have worked, I
fixed it working (I guess) as part of this patch set. Sometimes
I wonder how this code got upstream in the first place, it
obviously is not tested.
mach-s3c64xx/mach-smartq.c has the same problem and additionally
defines the *same* GPIO line for MOSI and MISO which is not going
to be accepted by gpiolib. As the lines were number 1,2,2 I assumed
it was a typo and use lines 1,2,3. A comment gives awat that line 0
is chip select though no actual SPI device is provided for the LCD
supposed to be on this bit-banged SPI bus. I left it intact instead
of just deleting the bus though.
Kill off board file code that try to initialize the SPI lines
to the same values that they will later be set by the spi_gpio
driver anyways. Given the huge number of weird things in these
board files I do not think this code is very tested or put in
with much afterthought anyways.
In order to assert that we do not get performance regressions on
this crucial bing-banged driver, a ran a script like this dumping the
Ilitek ILI9322 regmap 10000 times (it has no caching obviously) on
an otherwise idle system in two iterations before and after the
patches:
#!/bin/sh
for run in `seq 10000`
do
cat /debug/regmap/spi0.0/registers > /dev/null
done
Before the patch:
time test.sh
real 3m 41.03s
user 0m 29.41s
sys 3m 7.22s
time test.sh
real 3m 44.24s
user 0m 32.31s
sys 3m 7.60s
After the patch:
time test.sh
real 3m 41.32s
user 0m 28.92s
sys 3m 8.08s
time test.sh
real 3m 39.92s
user 0m 30.20s
sys 3m 5.56s
So any performance differences seems to be in the error margin.
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Acked-by: Olof Johansson <olof@lixom.net>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
2018-02-12 15:45:30 +03:00
# include <linux/gpio/machine.h>
2009-10-04 16:55:28 +04:00
# include <linux/init.h>
2011-07-25 15:44:46 +04:00
# include <linux/interrupt.h>
2011-11-10 16:06:22 +04:00
# include <linux/leds.h>
# include <linux/mmc/host.h>
2009-10-04 16:55:28 +04:00
# include <linux/platform_device.h>
2011-11-10 16:06:21 +04:00
# include <linux/pm.h>
2011-12-08 14:42:15 +04:00
# include <linux/spi/spi.h>
# include <linux/spi/spi_gpio.h>
# include <linux/spi/ads7846.h>
2011-07-25 15:44:46 +04:00
# include <asm/mach-au1x00/au1000.h>
2015-08-02 19:30:11 +03:00
# include <asm/mach-au1x00/gpio-au1000.h>
2011-07-25 15:44:46 +04:00
# include <asm/mach-au1x00/au1000_dma.h>
2011-11-10 16:06:22 +04:00
# include <asm/mach-au1x00/au1100_mmc.h>
2009-10-19 14:53:37 +04:00
# include <asm/mach-db1x00/bcsr.h>
2011-11-10 16:06:21 +04:00
# include <asm/reboot.h>
# include <prom.h>
# include "platform.h"
2009-10-04 16:55:28 +04:00
2011-11-10 16:06:22 +04:00
# define F_SWAPPED (bcsr_read(BCSR_STATUS) & BCSR_STATUS_DB1000_SWAPBOOT)
2014-02-20 17:59:24 +04:00
const char * get_system_type ( void ) ;
2011-08-12 13:39:44 +04:00
2014-02-20 17:59:24 +04:00
int __init db1000_board_setup ( void )
2011-11-10 16:06:22 +04:00
{
2014-02-20 17:59:24 +04:00
/* initialize board register space */
bcsr_init ( DB1000_BCSR_PHYS_ADDR ,
DB1000_BCSR_PHYS_ADDR + DB1000_BCSR_HEXLED_OFS ) ;
2011-11-10 16:06:22 +04:00
switch ( BCSR_WHOAMI_BOARD ( bcsr_read ( BCSR_WHOAMI ) ) ) {
case BCSR_WHOAMI_DB1000 :
case BCSR_WHOAMI_DB1500 :
case BCSR_WHOAMI_DB1100 :
2012-09-14 20:25:00 +04:00
case BCSR_WHOAMI_PB1500 :
case BCSR_WHOAMI_PB1500R2 :
case BCSR_WHOAMI_PB1100 :
2014-02-20 17:59:24 +04:00
pr_info ( " AMD Alchemy %s Board \n " , get_system_type ( ) ) ;
return 0 ;
2011-11-10 16:06:22 +04:00
}
2014-02-20 17:59:24 +04:00
return - ENODEV ;
2011-11-10 16:06:22 +04:00
}
2011-11-10 16:06:16 +04:00
static int db1500_map_pci_irq ( const struct pci_dev * d , u8 slot , u8 pin )
2011-08-12 13:39:44 +04:00
{
if ( ( slot < 12 ) | | ( slot > 13 ) | | pin = = 0 )
return - 1 ;
if ( slot = = 12 )
return ( pin = = 1 ) ? AU1500_PCI_INTA : 0xff ;
if ( slot = = 13 ) {
switch ( pin ) {
case 1 : return AU1500_PCI_INTA ;
case 2 : return AU1500_PCI_INTB ;
case 3 : return AU1500_PCI_INTC ;
case 4 : return AU1500_PCI_INTD ;
}
}
return - 1 ;
}
2018-12-19 10:08:03 +03:00
static u64 au1xxx_all_dmamask = DMA_BIT_MASK ( 32 ) ;
2011-08-12 13:39:44 +04:00
static struct resource alchemy_pci_host_res [ ] = {
[ 0 ] = {
. start = AU1500_PCI_PHYS_ADDR ,
. end = AU1500_PCI_PHYS_ADDR + 0xfff ,
. flags = IORESOURCE_MEM ,
} ,
} ;
2011-11-10 16:06:16 +04:00
static struct alchemy_pci_platdata db1500_pci_pd = {
. board_map_irq = db1500_map_pci_irq ,
2011-08-12 13:39:44 +04:00
} ;
2011-11-10 16:06:16 +04:00
static struct platform_device db1500_pci_host_dev = {
. dev . platform_data = & db1500_pci_pd ,
2011-08-12 13:39:44 +04:00
. name = " alchemy-pci " ,
. id = 0 ,
. num_resources = ARRAY_SIZE ( alchemy_pci_host_res ) ,
. resource = alchemy_pci_host_res ,
} ;
2014-02-20 17:59:24 +04:00
int __init db1500_pci_setup ( void )
2011-08-12 13:39:44 +04:00
{
2014-02-20 17:59:24 +04:00
return platform_device_register ( & db1500_pci_host_dev ) ;
2011-08-12 13:39:44 +04:00
}
2011-11-10 16:06:22 +04:00
2011-08-12 13:39:45 +04:00
static struct resource au1100_lcd_resources [ ] = {
[ 0 ] = {
. start = AU1100_LCD_PHYS_ADDR ,
. end = AU1100_LCD_PHYS_ADDR + 0x800 - 1 ,
. flags = IORESOURCE_MEM ,
} ,
[ 1 ] = {
. start = AU1100_LCD_INT ,
. end = AU1100_LCD_INT ,
. flags = IORESOURCE_IRQ ,
}
} ;
static struct platform_device au1100_lcd_device = {
. name = " au1100-lcd " ,
. id = 0 ,
. dev = {
2018-12-19 10:08:03 +03:00
. dma_mask = & au1xxx_all_dmamask ,
2011-08-12 13:39:45 +04:00
. coherent_dma_mask = DMA_BIT_MASK ( 32 ) ,
} ,
. num_resources = ARRAY_SIZE ( au1100_lcd_resources ) ,
. resource = au1100_lcd_resources ,
} ;
2011-07-25 15:44:46 +04:00
static struct resource alchemy_ac97c_res [ ] = {
[ 0 ] = {
. start = AU1000_AC97_PHYS_ADDR ,
. end = AU1000_AC97_PHYS_ADDR + 0xfff ,
. flags = IORESOURCE_MEM ,
} ,
[ 1 ] = {
. start = DMA_ID_AC97C_TX ,
. end = DMA_ID_AC97C_TX ,
. flags = IORESOURCE_DMA ,
} ,
[ 2 ] = {
. start = DMA_ID_AC97C_RX ,
. end = DMA_ID_AC97C_RX ,
. flags = IORESOURCE_DMA ,
} ,
} ;
static struct platform_device alchemy_ac97c_dev = {
. name = " alchemy-ac97c " ,
. id = - 1 ,
. resource = alchemy_ac97c_res ,
. num_resources = ARRAY_SIZE ( alchemy_ac97c_res ) ,
} ;
static struct platform_device alchemy_ac97c_dma_dev = {
. name = " alchemy-pcm-dma " ,
. id = 0 ,
} ;
static struct platform_device db1x00_codec_dev = {
. name = " ac97-codec " ,
. id = - 1 ,
} ;
static struct platform_device db1x00_audio_dev = {
. name = " db1000-audio " ,
2018-12-19 10:08:03 +03:00
. dev = {
. dma_mask = & au1xxx_all_dmamask ,
. coherent_dma_mask = DMA_BIT_MASK ( 32 ) ,
} ,
2011-07-25 15:44:46 +04:00
} ;
2011-11-10 16:06:22 +04:00
/******************************************************************************/
2023-09-05 10:06:56 +03:00
# ifdef CONFIG_MMC_AU1X
2011-11-10 16:06:22 +04:00
static irqreturn_t db1100_mmc_cd ( int irq , void * ptr )
{
2023-08-01 20:35:41 +03:00
mmc_detect_change ( ptr , msecs_to_jiffies ( 500 ) ) ;
2011-11-10 16:06:22 +04:00
return IRQ_HANDLED ;
}
static int db1100_mmc_cd_setup ( void * mmc_host , int en )
{
2012-09-14 20:25:00 +04:00
int ret = 0 , irq ;
if ( BCSR_WHOAMI_BOARD ( bcsr_read ( BCSR_WHOAMI ) ) = = BCSR_WHOAMI_DB1100 )
irq = AU1100_GPIO19_INT ;
else
irq = AU1100_GPIO14_INT ; /* PB1100 SD0 CD# */
2011-11-10 16:06:22 +04:00
if ( en ) {
2012-09-14 20:25:00 +04:00
irq_set_irq_type ( irq , IRQ_TYPE_EDGE_BOTH ) ;
ret = request_irq ( irq , db1100_mmc_cd , 0 ,
2011-11-10 16:06:22 +04:00
" sd0_cd " , mmc_host ) ;
} else
2012-09-14 20:25:00 +04:00
free_irq ( irq , mmc_host ) ;
2011-11-10 16:06:22 +04:00
return ret ;
}
static int db1100_mmc1_cd_setup ( void * mmc_host , int en )
{
2012-09-14 20:25:00 +04:00
int ret = 0 , irq ;
if ( BCSR_WHOAMI_BOARD ( bcsr_read ( BCSR_WHOAMI ) ) = = BCSR_WHOAMI_DB1100 )
irq = AU1100_GPIO20_INT ;
else
irq = AU1100_GPIO15_INT ; /* PB1100 SD1 CD# */
2011-11-10 16:06:22 +04:00
if ( en ) {
2012-09-14 20:25:00 +04:00
irq_set_irq_type ( irq , IRQ_TYPE_EDGE_BOTH ) ;
ret = request_irq ( irq , db1100_mmc_cd , 0 ,
2011-11-10 16:06:22 +04:00
" sd1_cd " , mmc_host ) ;
} else
2012-09-14 20:25:00 +04:00
free_irq ( irq , mmc_host ) ;
2011-11-10 16:06:22 +04:00
return ret ;
}
static int db1100_mmc_card_readonly ( void * mmc_host )
{
/* testing suggests that this bit is inverted */
return ( bcsr_read ( BCSR_STATUS ) & BCSR_STATUS_SD0WP ) ? 0 : 1 ;
}
static int db1100_mmc_card_inserted ( void * mmc_host )
{
return ! alchemy_gpio_get_value ( 19 ) ;
}
static void db1100_mmc_set_power ( void * mmc_host , int state )
{
2012-09-14 20:25:00 +04:00
int bit ;
if ( BCSR_WHOAMI_BOARD ( bcsr_read ( BCSR_WHOAMI ) ) = = BCSR_WHOAMI_DB1100 )
bit = BCSR_BOARD_SD0PWR ;
else
bit = BCSR_BOARD_PB1100_SD0PWR ;
2011-11-10 16:06:22 +04:00
if ( state ) {
2012-09-14 20:25:00 +04:00
bcsr_mod ( BCSR_BOARD , 0 , bit ) ;
2011-11-10 16:06:22 +04:00
msleep ( 400 ) ; /* stabilization time */
} else
2012-09-14 20:25:00 +04:00
bcsr_mod ( BCSR_BOARD , bit , 0 ) ;
2011-11-10 16:06:22 +04:00
}
static void db1100_mmcled_set ( struct led_classdev * led , enum led_brightness b )
{
if ( b ! = LED_OFF )
bcsr_mod ( BCSR_LEDS , BCSR_LEDS_LED0 , 0 ) ;
else
bcsr_mod ( BCSR_LEDS , 0 , BCSR_LEDS_LED0 ) ;
}
static struct led_classdev db1100_mmc_led = {
2013-01-22 15:59:30 +04:00
. brightness_set = db1100_mmcled_set ,
2011-11-10 16:06:22 +04:00
} ;
static int db1100_mmc1_card_readonly ( void * mmc_host )
{
return ( bcsr_read ( BCSR_BOARD ) & BCSR_BOARD_SD1WP ) ? 1 : 0 ;
}
static int db1100_mmc1_card_inserted ( void * mmc_host )
{
return ! alchemy_gpio_get_value ( 20 ) ;
}
static void db1100_mmc1_set_power ( void * mmc_host , int state )
{
2012-09-14 20:25:00 +04:00
int bit ;
if ( BCSR_WHOAMI_BOARD ( bcsr_read ( BCSR_WHOAMI ) ) = = BCSR_WHOAMI_DB1100 )
bit = BCSR_BOARD_SD1PWR ;
else
bit = BCSR_BOARD_PB1100_SD1PWR ;
2011-11-10 16:06:22 +04:00
if ( state ) {
2012-09-14 20:25:00 +04:00
bcsr_mod ( BCSR_BOARD , 0 , bit ) ;
2011-11-10 16:06:22 +04:00
msleep ( 400 ) ; /* stabilization time */
} else
2012-09-14 20:25:00 +04:00
bcsr_mod ( BCSR_BOARD , bit , 0 ) ;
2011-11-10 16:06:22 +04:00
}
static void db1100_mmc1led_set ( struct led_classdev * led , enum led_brightness b )
{
if ( b ! = LED_OFF )
bcsr_mod ( BCSR_LEDS , BCSR_LEDS_LED1 , 0 ) ;
else
bcsr_mod ( BCSR_LEDS , 0 , BCSR_LEDS_LED1 ) ;
}
static struct led_classdev db1100_mmc1_led = {
2013-01-22 15:59:30 +04:00
. brightness_set = db1100_mmc1led_set ,
2011-11-10 16:06:22 +04:00
} ;
static struct au1xmmc_platform_data db1100_mmc_platdata [ 2 ] = {
[ 0 ] = {
. cd_setup = db1100_mmc_cd_setup ,
. set_power = db1100_mmc_set_power ,
. card_inserted = db1100_mmc_card_inserted ,
. card_readonly = db1100_mmc_card_readonly ,
. led = & db1100_mmc_led ,
} ,
[ 1 ] = {
. cd_setup = db1100_mmc1_cd_setup ,
. set_power = db1100_mmc1_set_power ,
. card_inserted = db1100_mmc1_card_inserted ,
. card_readonly = db1100_mmc1_card_readonly ,
. led = & db1100_mmc1_led ,
} ,
} ;
static struct resource au1100_mmc0_resources [ ] = {
[ 0 ] = {
. start = AU1100_SD0_PHYS_ADDR ,
. end = AU1100_SD0_PHYS_ADDR + 0xfff ,
. flags = IORESOURCE_MEM ,
} ,
[ 1 ] = {
. start = AU1100_SD_INT ,
. end = AU1100_SD_INT ,
. flags = IORESOURCE_IRQ ,
} ,
[ 2 ] = {
. start = DMA_ID_SD0_TX ,
. end = DMA_ID_SD0_TX ,
. flags = IORESOURCE_DMA ,
} ,
[ 3 ] = {
. start = DMA_ID_SD0_RX ,
. end = DMA_ID_SD0_RX ,
. flags = IORESOURCE_DMA ,
}
} ;
static struct platform_device db1100_mmc0_dev = {
. name = " au1xxx-mmc " ,
. id = 0 ,
. dev = {
2018-12-19 10:08:03 +03:00
. dma_mask = & au1xxx_all_dmamask ,
2011-11-10 16:06:22 +04:00
. coherent_dma_mask = DMA_BIT_MASK ( 32 ) ,
. platform_data = & db1100_mmc_platdata [ 0 ] ,
} ,
. num_resources = ARRAY_SIZE ( au1100_mmc0_resources ) ,
. resource = au1100_mmc0_resources ,
} ;
static struct resource au1100_mmc1_res [ ] = {
[ 0 ] = {
. start = AU1100_SD1_PHYS_ADDR ,
. end = AU1100_SD1_PHYS_ADDR + 0xfff ,
. flags = IORESOURCE_MEM ,
} ,
[ 1 ] = {
. start = AU1100_SD_INT ,
. end = AU1100_SD_INT ,
. flags = IORESOURCE_IRQ ,
} ,
[ 2 ] = {
. start = DMA_ID_SD1_TX ,
. end = DMA_ID_SD1_TX ,
. flags = IORESOURCE_DMA ,
} ,
[ 3 ] = {
. start = DMA_ID_SD1_RX ,
. end = DMA_ID_SD1_RX ,
. flags = IORESOURCE_DMA ,
}
} ;
static struct platform_device db1100_mmc1_dev = {
. name = " au1xxx-mmc " ,
. id = 1 ,
. dev = {
2018-12-19 10:08:03 +03:00
. dma_mask = & au1xxx_all_dmamask ,
2011-11-10 16:06:22 +04:00
. coherent_dma_mask = DMA_BIT_MASK ( 32 ) ,
. platform_data = & db1100_mmc_platdata [ 1 ] ,
} ,
. num_resources = ARRAY_SIZE ( au1100_mmc1_res ) ,
. resource = au1100_mmc1_res ,
} ;
2023-09-05 10:06:56 +03:00
# endif /* CONFIG_MMC_AU1X */
2011-11-10 16:06:22 +04:00
2011-12-08 14:42:15 +04:00
/******************************************************************************/
2011-12-08 14:42:15 +04:00
static struct ads7846_platform_data db1100_touch_pd = {
. model = 7846 ,
. vref_mv = 3300 ,
} ;
static struct spi_gpio_platform_data db1100_spictl_pd = {
. num_chipselect = 1 ,
} ;
2023-05-09 00:20:06 +03:00
static struct gpiod_lookup_table db1100_touch_gpio_table = {
. dev_id = " spi0.0 " ,
. table = {
GPIO_LOOKUP ( " alchemy-gpio2 " , 21 ,
" pendown " , GPIO_ACTIVE_LOW ) ,
{ }
} ,
} ;
2011-12-08 14:42:15 +04:00
static struct spi_board_info db1100_spi_info [ ] __initdata = {
[ 0 ] = {
. modalias = " ads7846 " ,
. max_speed_hz = 3250000 ,
. bus_num = 0 ,
. chip_select = 0 ,
. mode = 0 ,
. irq = AU1100_GPIO21_INT ,
. platform_data = & db1100_touch_pd ,
} ,
} ;
static struct platform_device db1100_spi_dev = {
. name = " spi_gpio " ,
. id = 0 ,
. dev = {
. platform_data = & db1100_spictl_pd ,
2018-12-19 10:08:03 +03:00
. dma_mask = & au1xxx_all_dmamask ,
. coherent_dma_mask = DMA_BIT_MASK ( 32 ) ,
2011-12-08 14:42:15 +04:00
} ,
} ;
spi: spi-gpio: Rewrite to use GPIO descriptors
This converts the bit-banged GPIO SPI driver to looking up and
using GPIO descriptors to get a handle on GPIO lines for SCK,
MOSI, MISO and all CS lines.
All existing board files are converted in one go to keep it all
consistent. With these conversions I rarely find any interrim
steps that makes any sense.
Device tree probing and GPIO handling should work like before
also after this patch.
For board files, we stop using controller data to pass the GPIO
line for chip select, instead we pass this as a GPIO descriptor
lookup like everything else.
In some s3c24xx machines the names of the SPI devices were set to
"spi-gpio" rather than "spi_gpio" which can never have worked, I
fixed it working (I guess) as part of this patch set. Sometimes
I wonder how this code got upstream in the first place, it
obviously is not tested.
mach-s3c64xx/mach-smartq.c has the same problem and additionally
defines the *same* GPIO line for MOSI and MISO which is not going
to be accepted by gpiolib. As the lines were number 1,2,2 I assumed
it was a typo and use lines 1,2,3. A comment gives awat that line 0
is chip select though no actual SPI device is provided for the LCD
supposed to be on this bit-banged SPI bus. I left it intact instead
of just deleting the bus though.
Kill off board file code that try to initialize the SPI lines
to the same values that they will later be set by the spi_gpio
driver anyways. Given the huge number of weird things in these
board files I do not think this code is very tested or put in
with much afterthought anyways.
In order to assert that we do not get performance regressions on
this crucial bing-banged driver, a ran a script like this dumping the
Ilitek ILI9322 regmap 10000 times (it has no caching obviously) on
an otherwise idle system in two iterations before and after the
patches:
#!/bin/sh
for run in `seq 10000`
do
cat /debug/regmap/spi0.0/registers > /dev/null
done
Before the patch:
time test.sh
real 3m 41.03s
user 0m 29.41s
sys 3m 7.22s
time test.sh
real 3m 44.24s
user 0m 32.31s
sys 3m 7.60s
After the patch:
time test.sh
real 3m 41.32s
user 0m 28.92s
sys 3m 8.08s
time test.sh
real 3m 39.92s
user 0m 30.20s
sys 3m 5.56s
So any performance differences seems to be in the error margin.
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Acked-by: Olof Johansson <olof@lixom.net>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
2018-02-12 15:45:30 +03:00
/*
* Alchemy GPIO 2 has its base at 200 so the GPIO lines
* 207 thru 210 are GPIOs at offset 7 thru 10 at this chip .
*/
static struct gpiod_lookup_table db1100_spi_gpiod_table = {
. dev_id = " spi_gpio " ,
. table = {
GPIO_LOOKUP ( " alchemy-gpio2 " , 9 ,
" sck " , GPIO_ACTIVE_HIGH ) ,
GPIO_LOOKUP ( " alchemy-gpio2 " , 8 ,
" mosi " , GPIO_ACTIVE_HIGH ) ,
GPIO_LOOKUP ( " alchemy-gpio2 " , 7 ,
" miso " , GPIO_ACTIVE_HIGH ) ,
GPIO_LOOKUP ( " alchemy-gpio2 " , 10 ,
" cs " , GPIO_ACTIVE_HIGH ) ,
{ } ,
} ,
} ;
2011-12-08 14:42:15 +04:00
2011-11-10 16:06:22 +04:00
static struct platform_device * db1x00_devs [ ] = {
& db1x00_codec_dev ,
& alchemy_ac97c_dma_dev ,
& alchemy_ac97c_dev ,
& db1x00_audio_dev ,
} ;
static struct platform_device * db1100_devs [ ] = {
& au1100_lcd_device ,
2023-09-05 10:06:56 +03:00
# ifdef CONFIG_MMC_AU1X
2011-11-10 16:06:22 +04:00
& db1100_mmc0_dev ,
& db1100_mmc1_dev ,
2023-09-05 10:06:56 +03:00
# endif
2011-11-10 16:06:22 +04:00
} ;
2014-02-20 17:59:24 +04:00
int __init db1000_dev_setup ( void )
2009-10-04 16:55:28 +04:00
{
2011-11-10 16:06:22 +04:00
int board = BCSR_WHOAMI_BOARD ( bcsr_read ( BCSR_WHOAMI ) ) ;
2012-09-14 20:25:00 +04:00
int c0 , c1 , d0 , d1 , s0 , s1 , flashsize = 32 , twosocks = 1 ;
2011-12-08 14:42:15 +04:00
unsigned long pfc ;
2014-07-23 18:36:54 +04:00
struct clk * c , * p ;
2011-11-10 16:06:22 +04:00
if ( board = = BCSR_WHOAMI_DB1500 ) {
c0 = AU1500_GPIO2_INT ;
c1 = AU1500_GPIO5_INT ;
2016-03-02 12:34:43 +03:00
d0 = 0 ; /* GPIO number, NOT irq! */
d1 = 3 ; /* GPIO number, NOT irq! */
2011-11-10 16:06:22 +04:00
s0 = AU1500_GPIO1_INT ;
s1 = AU1500_GPIO4_INT ;
} else if ( board = = BCSR_WHOAMI_DB1100 ) {
c0 = AU1100_GPIO2_INT ;
c1 = AU1100_GPIO5_INT ;
2016-03-02 12:34:43 +03:00
d0 = 0 ; /* GPIO number, NOT irq! */
d1 = 3 ; /* GPIO number, NOT irq! */
2011-11-10 16:06:22 +04:00
s0 = AU1100_GPIO1_INT ;
s1 = AU1100_GPIO4_INT ;
2011-11-10 16:06:22 +04:00
2014-01-29 22:11:46 +04:00
gpio_request ( 19 , " sd0_cd " ) ;
gpio_request ( 20 , " sd1_cd " ) ;
2011-11-10 16:06:22 +04:00
gpio_direction_input ( 19 ) ; /* sd0 cd# */
gpio_direction_input ( 20 ) ; /* sd1 cd# */
2011-12-08 14:42:15 +04:00
/* spi_gpio on SSI0 pins */
2014-07-23 18:36:24 +04:00
pfc = alchemy_rdsys ( AU1000_SYS_PINFUNC ) ;
2011-12-08 14:42:15 +04:00
pfc | = ( 1 < < 0 ) ; /* SSI0 pins as GPIOs */
2014-07-23 18:36:24 +04:00
alchemy_wrsys ( pfc , AU1000_SYS_PINFUNC ) ;
2011-12-08 14:42:15 +04:00
2023-05-09 00:20:06 +03:00
gpiod_add_lookup_table ( & db1100_touch_gpio_table ) ;
2011-12-08 14:42:15 +04:00
spi_register_board_info ( db1100_spi_info ,
ARRAY_SIZE ( db1100_spi_info ) ) ;
2011-11-10 16:06:22 +04:00
2014-07-23 18:36:54 +04:00
/* link LCD clock to AUXPLL */
p = clk_get ( NULL , " auxpll_clk " ) ;
c = clk_get ( NULL , " lcd_intclk " ) ;
if ( ! IS_ERR ( c ) & & ! IS_ERR ( p ) ) {
clk_set_parent ( c , p ) ;
clk_set_rate ( c , clk_get_rate ( p ) ) ;
}
if ( ! IS_ERR ( c ) )
clk_put ( c ) ;
if ( ! IS_ERR ( p ) )
clk_put ( p ) ;
2011-11-10 16:06:22 +04:00
platform_add_devices ( db1100_devs , ARRAY_SIZE ( db1100_devs ) ) ;
spi: spi-gpio: Rewrite to use GPIO descriptors
This converts the bit-banged GPIO SPI driver to looking up and
using GPIO descriptors to get a handle on GPIO lines for SCK,
MOSI, MISO and all CS lines.
All existing board files are converted in one go to keep it all
consistent. With these conversions I rarely find any interrim
steps that makes any sense.
Device tree probing and GPIO handling should work like before
also after this patch.
For board files, we stop using controller data to pass the GPIO
line for chip select, instead we pass this as a GPIO descriptor
lookup like everything else.
In some s3c24xx machines the names of the SPI devices were set to
"spi-gpio" rather than "spi_gpio" which can never have worked, I
fixed it working (I guess) as part of this patch set. Sometimes
I wonder how this code got upstream in the first place, it
obviously is not tested.
mach-s3c64xx/mach-smartq.c has the same problem and additionally
defines the *same* GPIO line for MOSI and MISO which is not going
to be accepted by gpiolib. As the lines were number 1,2,2 I assumed
it was a typo and use lines 1,2,3. A comment gives awat that line 0
is chip select though no actual SPI device is provided for the LCD
supposed to be on this bit-banged SPI bus. I left it intact instead
of just deleting the bus though.
Kill off board file code that try to initialize the SPI lines
to the same values that they will later be set by the spi_gpio
driver anyways. Given the huge number of weird things in these
board files I do not think this code is very tested or put in
with much afterthought anyways.
In order to assert that we do not get performance regressions on
this crucial bing-banged driver, a ran a script like this dumping the
Ilitek ILI9322 regmap 10000 times (it has no caching obviously) on
an otherwise idle system in two iterations before and after the
patches:
#!/bin/sh
for run in `seq 10000`
do
cat /debug/regmap/spi0.0/registers > /dev/null
done
Before the patch:
time test.sh
real 3m 41.03s
user 0m 29.41s
sys 3m 7.22s
time test.sh
real 3m 44.24s
user 0m 32.31s
sys 3m 7.60s
After the patch:
time test.sh
real 3m 41.32s
user 0m 28.92s
sys 3m 8.08s
time test.sh
real 3m 39.92s
user 0m 30.20s
sys 3m 5.56s
So any performance differences seems to be in the error margin.
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Acked-by: Olof Johansson <olof@lixom.net>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
2018-02-12 15:45:30 +03:00
gpiod_add_lookup_table ( & db1100_spi_gpiod_table ) ;
2012-09-14 20:25:00 +04:00
platform_device_register ( & db1100_spi_dev ) ;
2011-11-10 16:06:22 +04:00
} else if ( board = = BCSR_WHOAMI_DB1000 ) {
c0 = AU1000_GPIO2_INT ;
c1 = AU1000_GPIO5_INT ;
2016-03-02 12:34:43 +03:00
d0 = 0 ; /* GPIO number, NOT irq! */
d1 = 3 ; /* GPIO number, NOT irq! */
2011-11-10 16:06:22 +04:00
s0 = AU1000_GPIO1_INT ;
s1 = AU1000_GPIO4_INT ;
2012-09-14 20:25:00 +04:00
} else if ( ( board = = BCSR_WHOAMI_PB1500 ) | |
( board = = BCSR_WHOAMI_PB1500R2 ) ) {
c0 = AU1500_GPIO203_INT ;
2016-03-02 12:34:43 +03:00
d0 = 1 ; /* GPIO number, NOT irq! */
2012-09-14 20:25:00 +04:00
s0 = AU1500_GPIO202_INT ;
twosocks = 0 ;
flashsize = 64 ;
/* RTC and daughtercard irqs */
irq_set_irq_type ( AU1500_GPIO204_INT , IRQ_TYPE_LEVEL_LOW ) ;
irq_set_irq_type ( AU1500_GPIO205_INT , IRQ_TYPE_LEVEL_LOW ) ;
/* EPSON S1D13806 0x1b000000
2013-01-22 15:59:30 +04:00
* SRAM 1 MB / 2 MB 0x1a000000
2012-09-14 20:25:00 +04:00
* DS1693 RTC 0x0c000000
*/
} else if ( board = = BCSR_WHOAMI_PB1100 ) {
c0 = AU1100_GPIO11_INT ;
2016-03-02 12:34:43 +03:00
d0 = 9 ; /* GPIO number, NOT irq! */
2012-09-14 20:25:00 +04:00
s0 = AU1100_GPIO10_INT ;
twosocks = 0 ;
flashsize = 64 ;
/* pendown, rtc, daughtercard irqs */
irq_set_irq_type ( AU1100_GPIO8_INT , IRQ_TYPE_LEVEL_LOW ) ;
irq_set_irq_type ( AU1100_GPIO12_INT , IRQ_TYPE_LEVEL_LOW ) ;
irq_set_irq_type ( AU1100_GPIO13_INT , IRQ_TYPE_LEVEL_LOW ) ;
/* EPSON S1D13806 0x1b000000
2013-01-22 15:59:30 +04:00
* SRAM 1 MB / 2 MB 0x1a000000
2012-09-14 20:25:00 +04:00
* DiskOnChip 0x0d000000
* DS1693 RTC 0x0c000000
*/
platform_add_devices ( db1100_devs , ARRAY_SIZE ( db1100_devs ) ) ;
2011-11-10 16:06:22 +04:00
} else
return 0 ; /* unknown board, no further dev setup to do */
irq_set_irq_type ( c0 , IRQ_TYPE_LEVEL_LOW ) ;
irq_set_irq_type ( s0 , IRQ_TYPE_LEVEL_LOW ) ;
2011-11-10 16:06:21 +04:00
2011-08-12 13:39:40 +04:00
db1x_register_pcmcia_socket (
AU1000_PCMCIA_ATTR_PHYS_ADDR ,
AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1 ,
AU1000_PCMCIA_MEM_PHYS_ADDR ,
AU1000_PCMCIA_MEM_PHYS_ADDR + 0x000400000 - 1 ,
AU1000_PCMCIA_IO_PHYS_ADDR ,
AU1000_PCMCIA_IO_PHYS_ADDR + 0x000010000 - 1 ,
2013-01-22 15:59:30 +04:00
c0 , d0 , /*s0*/ 0 , 0 , 0 ) ;
2009-10-04 16:55:28 +04:00
2012-09-14 20:25:00 +04:00
if ( twosocks ) {
irq_set_irq_type ( c1 , IRQ_TYPE_LEVEL_LOW ) ;
irq_set_irq_type ( s1 , IRQ_TYPE_LEVEL_LOW ) ;
db1x_register_pcmcia_socket (
AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x004000000 ,
AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x004400000 - 1 ,
AU1000_PCMCIA_MEM_PHYS_ADDR + 0x004000000 ,
AU1000_PCMCIA_MEM_PHYS_ADDR + 0x004400000 - 1 ,
AU1000_PCMCIA_IO_PHYS_ADDR + 0x004000000 ,
AU1000_PCMCIA_IO_PHYS_ADDR + 0x004010000 - 1 ,
2013-01-22 15:59:30 +04:00
c1 , d1 , /*s1*/ 0 , 0 , 1 ) ;
2012-09-14 20:25:00 +04:00
}
2011-07-25 15:44:46 +04:00
2011-11-10 16:06:22 +04:00
platform_add_devices ( db1x00_devs , ARRAY_SIZE ( db1x00_devs ) ) ;
2012-09-14 20:25:00 +04:00
db1x_register_norflash ( flashsize < < 20 , 4 /* 32bit */ , F_SWAPPED ) ;
2009-10-04 16:55:28 +04:00
return 0 ;
}