2018-11-10 16:49:16 +01:00
// SPDX-License-Identifier: GPL-2.0
2013-02-11 19:47:56 -07:00
/*
* BCM2835 master mode driver
*/
# include <linux/clk.h>
2019-06-08 10:14:43 -07:00
# include <linux/clkdev.h>
# include <linux/clk-provider.h>
2013-02-11 19:47:56 -07:00
# include <linux/completion.h>
# include <linux/err.h>
# include <linux/i2c.h>
# include <linux/interrupt.h>
# include <linux/io.h>
# include <linux/module.h>
# include <linux/platform_device.h>
# include <linux/slab.h>
# define BCM2835_I2C_C 0x0
# define BCM2835_I2C_S 0x4
# define BCM2835_I2C_DLEN 0x8
# define BCM2835_I2C_A 0xc
# define BCM2835_I2C_FIFO 0x10
# define BCM2835_I2C_DIV 0x14
# define BCM2835_I2C_DEL 0x18
# define BCM2835_I2C_CLKT 0x1c
# define BCM2835_I2C_C_READ BIT(0)
# define BCM2835_I2C_C_CLEAR BIT(4) /* bits 4 and 5 both clear */
# define BCM2835_I2C_C_ST BIT(7)
# define BCM2835_I2C_C_INTD BIT(8)
# define BCM2835_I2C_C_INTT BIT(9)
# define BCM2835_I2C_C_INTR BIT(10)
# define BCM2835_I2C_C_I2CEN BIT(15)
# define BCM2835_I2C_S_TA BIT(0)
# define BCM2835_I2C_S_DONE BIT(1)
# define BCM2835_I2C_S_TXW BIT(2)
# define BCM2835_I2C_S_RXR BIT(3)
# define BCM2835_I2C_S_TXD BIT(4)
# define BCM2835_I2C_S_RXD BIT(5)
# define BCM2835_I2C_S_TXE BIT(6)
# define BCM2835_I2C_S_RXF BIT(7)
# define BCM2835_I2C_S_ERR BIT(8)
# define BCM2835_I2C_S_CLKT BIT(9)
# define BCM2835_I2C_S_LEN BIT(10) /* Fake bit for SW error reporting */
2018-02-08 14:54:05 +01:00
# define BCM2835_I2C_FEDL_SHIFT 16
# define BCM2835_I2C_REDL_SHIFT 0
2015-06-18 11:10:11 +02:00
# define BCM2835_I2C_CDIV_MIN 0x0002
# define BCM2835_I2C_CDIV_MAX 0xFFFE
2013-02-11 19:47:56 -07:00
struct bcm2835_i2c_dev {
struct device * dev ;
void __iomem * regs ;
int irq ;
struct i2c_adapter adapter ;
struct completion completion ;
2016-10-03 22:06:08 +02:00
struct i2c_msg * curr_msg ;
2016-10-03 22:06:12 +02:00
int num_msgs ;
2013-02-11 19:47:56 -07:00
u32 msg_err ;
u8 * msg_buf ;
size_t msg_buf_remaining ;
} ;
static inline void bcm2835_i2c_writel ( struct bcm2835_i2c_dev * i2c_dev ,
u32 reg , u32 val )
{
writel ( val , i2c_dev - > regs + reg ) ;
}
static inline u32 bcm2835_i2c_readl ( struct bcm2835_i2c_dev * i2c_dev , u32 reg )
{
return readl ( i2c_dev - > regs + reg ) ;
}
2019-06-08 10:14:43 -07:00
# define to_clk_bcm2835_i2c(_hw) container_of(_hw, struct clk_bcm2835_i2c, hw)
struct clk_bcm2835_i2c {
struct clk_hw hw ;
struct bcm2835_i2c_dev * i2c_dev ;
} ;
static int clk_bcm2835_i2c_calc_divider ( unsigned long rate ,
unsigned long parent_rate )
2016-10-03 22:06:14 +02:00
{
2019-06-08 10:14:43 -07:00
u32 divider = DIV_ROUND_UP ( parent_rate , rate ) ;
2016-10-03 22:06:14 +02:00
/*
* Per the datasheet , the register is always interpreted as an even
* number , by rounding down . In other words , the LSB is ignored . So ,
* if the LSB is set , increment the divider to avoid any issue .
*/
if ( divider & 1 )
divider + + ;
if ( ( divider < BCM2835_I2C_CDIV_MIN ) | |
2019-06-08 10:14:43 -07:00
( divider > BCM2835_I2C_CDIV_MAX ) )
2016-10-03 22:06:14 +02:00
return - EINVAL ;
2019-06-08 10:14:43 -07:00
return divider ;
}
static int clk_bcm2835_i2c_set_rate ( struct clk_hw * hw , unsigned long rate ,
unsigned long parent_rate )
{
struct clk_bcm2835_i2c * div = to_clk_bcm2835_i2c ( hw ) ;
u32 redl , fedl ;
u32 divider = clk_bcm2835_i2c_calc_divider ( rate , parent_rate ) ;
if ( divider = = - EINVAL )
return - EINVAL ;
bcm2835_i2c_writel ( div - > i2c_dev , BCM2835_I2C_DIV , divider ) ;
2016-10-03 22:06:14 +02:00
2018-02-08 14:54:05 +01:00
/*
* Number of core clocks to wait after falling edge before
* outputting the next data bit . Note that both FEDL and REDL
* can ' t be greater than CDIV / 2.
*/
fedl = max ( divider / 16 , 1u ) ;
/*
* Number of core clocks to wait after rising edge before
* sampling the next incoming data bit .
*/
redl = max ( divider / 4 , 1u ) ;
2019-06-08 10:14:43 -07:00
bcm2835_i2c_writel ( div - > i2c_dev , BCM2835_I2C_DEL ,
2018-02-08 14:54:05 +01:00
( fedl < < BCM2835_I2C_FEDL_SHIFT ) |
( redl < < BCM2835_I2C_REDL_SHIFT ) ) ;
2016-10-03 22:06:14 +02:00
return 0 ;
}
2019-06-08 10:14:43 -07:00
static long clk_bcm2835_i2c_round_rate ( struct clk_hw * hw , unsigned long rate ,
unsigned long * parent_rate )
{
u32 divider = clk_bcm2835_i2c_calc_divider ( rate , * parent_rate ) ;
return DIV_ROUND_UP ( * parent_rate , divider ) ;
}
static unsigned long clk_bcm2835_i2c_recalc_rate ( struct clk_hw * hw ,
unsigned long parent_rate )
{
struct clk_bcm2835_i2c * div = to_clk_bcm2835_i2c ( hw ) ;
u32 divider = bcm2835_i2c_readl ( div - > i2c_dev , BCM2835_I2C_DIV ) ;
return DIV_ROUND_UP ( parent_rate , divider ) ;
}
static const struct clk_ops clk_bcm2835_i2c_ops = {
. set_rate = clk_bcm2835_i2c_set_rate ,
. round_rate = clk_bcm2835_i2c_round_rate ,
. recalc_rate = clk_bcm2835_i2c_recalc_rate ,
} ;
static struct clk * bcm2835_i2c_register_div ( struct device * dev ,
2019-06-21 03:52:50 -07:00
struct clk * mclk ,
2019-06-08 10:14:43 -07:00
struct bcm2835_i2c_dev * i2c_dev )
{
struct clk_init_data init ;
struct clk_bcm2835_i2c * priv ;
char name [ 32 ] ;
2019-06-21 03:52:50 -07:00
const char * mclk_name ;
2019-06-08 10:14:43 -07:00
snprintf ( name , sizeof ( name ) , " %s_div " , dev_name ( dev ) ) ;
2019-06-21 03:52:50 -07:00
mclk_name = __clk_get_name ( mclk ) ;
2019-06-08 10:14:43 -07:00
init . ops = & clk_bcm2835_i2c_ops ;
init . name = name ;
init . parent_names = ( const char * [ ] ) { mclk_name } ;
init . num_parents = 1 ;
init . flags = 0 ;
priv = devm_kzalloc ( dev , sizeof ( struct clk_bcm2835_i2c ) , GFP_KERNEL ) ;
if ( priv = = NULL )
return ERR_PTR ( - ENOMEM ) ;
priv - > hw . init = & init ;
priv - > i2c_dev = i2c_dev ;
clk_hw_register_clkdev ( & priv - > hw , " div " , dev_name ( dev ) ) ;
return devm_clk_register ( dev , & priv - > hw ) ;
}
2013-02-11 19:47:56 -07:00
static void bcm2835_fill_txfifo ( struct bcm2835_i2c_dev * i2c_dev )
{
u32 val ;
while ( i2c_dev - > msg_buf_remaining ) {
val = bcm2835_i2c_readl ( i2c_dev , BCM2835_I2C_S ) ;
if ( ! ( val & BCM2835_I2C_S_TXD ) )
break ;
bcm2835_i2c_writel ( i2c_dev , BCM2835_I2C_FIFO ,
* i2c_dev - > msg_buf ) ;
i2c_dev - > msg_buf + + ;
i2c_dev - > msg_buf_remaining - - ;
}
}
static void bcm2835_drain_rxfifo ( struct bcm2835_i2c_dev * i2c_dev )
{
u32 val ;
while ( i2c_dev - > msg_buf_remaining ) {
val = bcm2835_i2c_readl ( i2c_dev , BCM2835_I2C_S ) ;
if ( ! ( val & BCM2835_I2C_S_RXD ) )
break ;
* i2c_dev - > msg_buf = bcm2835_i2c_readl ( i2c_dev ,
BCM2835_I2C_FIFO ) ;
i2c_dev - > msg_buf + + ;
i2c_dev - > msg_buf_remaining - - ;
}
}
2016-10-03 22:06:12 +02:00
/*
* Repeated Start Condition ( Sr )
* The BCM2835 ARM Peripherals datasheet mentions a way to trigger a Sr when it
* talks about reading from a slave with 10 bit address . This is achieved by
* issuing a write , poll the I2CS . TA flag and wait for it to be set , and then
* issue a read .
* A comment in https : //github.com/raspberrypi/linux/issues/254 shows how the
* firmware actually does it using polling and says that it ' s a workaround for
* a problem in the state machine .
* It turns out that it is possible to use the TXW interrupt to know when the
* transfer is active , provided the FIFO has not been prefilled .
*/
static void bcm2835_i2c_start_transfer ( struct bcm2835_i2c_dev * i2c_dev )
{
u32 c = BCM2835_I2C_C_ST | BCM2835_I2C_C_I2CEN ;
struct i2c_msg * msg = i2c_dev - > curr_msg ;
bool last_msg = ( i2c_dev - > num_msgs = = 1 ) ;
if ( ! i2c_dev - > num_msgs )
return ;
i2c_dev - > num_msgs - - ;
i2c_dev - > msg_buf = msg - > buf ;
i2c_dev - > msg_buf_remaining = msg - > len ;
if ( msg - > flags & I2C_M_RD )
c | = BCM2835_I2C_C_READ | BCM2835_I2C_C_INTR ;
else
c | = BCM2835_I2C_C_INTT ;
if ( last_msg )
c | = BCM2835_I2C_C_INTD ;
bcm2835_i2c_writel ( i2c_dev , BCM2835_I2C_A , msg - > addr ) ;
bcm2835_i2c_writel ( i2c_dev , BCM2835_I2C_DLEN , msg - > len ) ;
bcm2835_i2c_writel ( i2c_dev , BCM2835_I2C_C , c ) ;
}
2018-12-27 16:42:25 +01:00
static void bcm2835_i2c_finish_transfer ( struct bcm2835_i2c_dev * i2c_dev )
{
i2c_dev - > curr_msg = NULL ;
i2c_dev - > num_msgs = 0 ;
i2c_dev - > msg_buf = NULL ;
i2c_dev - > msg_buf_remaining = 0 ;
}
2016-10-03 22:06:09 +02:00
/*
* Note about I2C_C_CLEAR on error :
* The I2C_C_CLEAR on errors will take some time to resolve - - if you were in
* non - idle state and I2C_C_READ , it sets an abort_rx flag and runs through
* the state machine to send a NACK and a STOP . Since we ' re setting CLEAR
* without I2CEN , that NACK will be hanging around queued up for next time
* we start the engine .
*/
2013-02-11 19:47:56 -07:00
static irqreturn_t bcm2835_i2c_isr ( int this_irq , void * data )
{
struct bcm2835_i2c_dev * i2c_dev = data ;
u32 val , err ;
val = bcm2835_i2c_readl ( i2c_dev , BCM2835_I2C_S ) ;
err = val & ( BCM2835_I2C_S_CLKT | BCM2835_I2C_S_ERR ) ;
if ( err ) {
i2c_dev - > msg_err = err ;
2016-10-03 22:06:09 +02:00
goto complete ;
2013-02-11 19:47:56 -07:00
}
if ( val & BCM2835_I2C_S_DONE ) {
2017-02-16 21:20:45 +00:00
if ( ! i2c_dev - > curr_msg ) {
dev_err ( i2c_dev - > dev , " Got unexpected interrupt (from firmware?) \n " ) ;
} else if ( i2c_dev - > curr_msg - > flags & I2C_M_RD ) {
2016-10-03 22:06:08 +02:00
bcm2835_drain_rxfifo ( i2c_dev ) ;
val = bcm2835_i2c_readl ( i2c_dev , BCM2835_I2C_S ) ;
}
if ( ( val & BCM2835_I2C_S_RXD ) | | i2c_dev - > msg_buf_remaining )
2013-02-11 19:47:56 -07:00
i2c_dev - > msg_err = BCM2835_I2C_S_LEN ;
else
i2c_dev - > msg_err = 0 ;
2016-10-03 22:06:09 +02:00
goto complete ;
2013-02-11 19:47:56 -07:00
}
2016-10-03 22:06:08 +02:00
if ( val & BCM2835_I2C_S_TXW ) {
2016-10-03 22:06:09 +02:00
if ( ! i2c_dev - > msg_buf_remaining ) {
i2c_dev - > msg_err = val | BCM2835_I2C_S_LEN ;
goto complete ;
}
2013-02-11 19:47:56 -07:00
bcm2835_fill_txfifo ( i2c_dev ) ;
2016-10-03 22:06:12 +02:00
if ( i2c_dev - > num_msgs & & ! i2c_dev - > msg_buf_remaining ) {
i2c_dev - > curr_msg + + ;
bcm2835_i2c_start_transfer ( i2c_dev ) ;
}
2013-02-11 19:47:56 -07:00
return IRQ_HANDLED ;
}
2016-10-03 22:06:08 +02:00
if ( val & BCM2835_I2C_S_RXR ) {
2016-10-03 22:06:09 +02:00
if ( ! i2c_dev - > msg_buf_remaining ) {
i2c_dev - > msg_err = val | BCM2835_I2C_S_LEN ;
goto complete ;
}
2016-10-03 22:06:08 +02:00
bcm2835_drain_rxfifo ( i2c_dev ) ;
return IRQ_HANDLED ;
}
2013-02-11 19:47:56 -07:00
return IRQ_NONE ;
2016-10-03 22:06:09 +02:00
complete :
bcm2835_i2c_writel ( i2c_dev , BCM2835_I2C_C , BCM2835_I2C_C_CLEAR ) ;
bcm2835_i2c_writel ( i2c_dev , BCM2835_I2C_S , BCM2835_I2C_S_CLKT |
BCM2835_I2C_S_ERR | BCM2835_I2C_S_DONE ) ;
complete ( & i2c_dev - > completion ) ;
return IRQ_HANDLED ;
2013-02-11 19:47:56 -07:00
}
2016-10-03 22:06:12 +02:00
static int bcm2835_i2c_xfer ( struct i2c_adapter * adap , struct i2c_msg msgs [ ] ,
int num )
2013-02-11 19:47:56 -07:00
{
2016-10-03 22:06:12 +02:00
struct bcm2835_i2c_dev * i2c_dev = i2c_get_adapdata ( adap ) ;
2015-02-08 06:04:18 -05:00
unsigned long time_left ;
2019-06-08 10:14:43 -07:00
int i ;
2013-02-11 19:47:56 -07:00
2016-10-03 22:06:12 +02:00
for ( i = 0 ; i < ( num - 1 ) ; i + + )
if ( msgs [ i ] . flags & I2C_M_RD ) {
dev_warn_once ( i2c_dev - > dev ,
" only one read message supported, has to be last \n " ) ;
return - EOPNOTSUPP ;
}
2013-02-11 19:47:56 -07:00
2016-10-03 22:06:12 +02:00
i2c_dev - > curr_msg = msgs ;
i2c_dev - > num_msgs = num ;
reinit_completion ( & i2c_dev - > completion ) ;
2013-02-11 19:47:56 -07:00
2016-10-03 22:06:12 +02:00
bcm2835_i2c_start_transfer ( i2c_dev ) ;
2013-02-11 19:47:56 -07:00
time_left = wait_for_completion_timeout ( & i2c_dev - > completion ,
2016-10-03 22:06:13 +02:00
adap - > timeout ) ;
2018-12-27 16:42:25 +01:00
bcm2835_i2c_finish_transfer ( i2c_dev ) ;
2013-02-11 19:47:56 -07:00
if ( ! time_left ) {
2016-10-03 22:06:09 +02:00
bcm2835_i2c_writel ( i2c_dev , BCM2835_I2C_C ,
BCM2835_I2C_C_CLEAR ) ;
2013-02-11 19:47:56 -07:00
dev_err ( i2c_dev - > dev , " i2c transfer timed out \n " ) ;
return - ETIMEDOUT ;
}
2016-10-03 22:06:12 +02:00
if ( ! i2c_dev - > msg_err )
return num ;
2013-02-11 19:47:56 -07:00
2016-10-03 22:06:10 +02:00
dev_dbg ( i2c_dev - > dev , " i2c transfer failed: %x \n " , i2c_dev - > msg_err ) ;
2013-02-11 19:47:56 -07:00
if ( i2c_dev - > msg_err & BCM2835_I2C_S_ERR )
return - EREMOTEIO ;
2016-10-03 22:06:12 +02:00
return - EIO ;
2013-02-11 19:47:56 -07:00
}
static u32 bcm2835_i2c_func ( struct i2c_adapter * adap )
{
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL ;
}
static const struct i2c_algorithm bcm2835_i2c_algo = {
. master_xfer = bcm2835_i2c_xfer ,
. functionality = bcm2835_i2c_func ,
} ;
2015-10-29 12:34:25 +01:00
/*
* This HW was reported to have problems with clock stretching :
* http : //www.advamation.com/knowhow/raspberrypi/rpi-i2c-bug.html
* https : //www.raspberrypi.org/forums/viewtopic.php?p=146272
*/
static const struct i2c_adapter_quirks bcm2835_i2c_quirks = {
. flags = I2C_AQ_NO_CLK_STRETCH ,
} ;
2013-02-11 19:47:56 -07:00
static int bcm2835_i2c_probe ( struct platform_device * pdev )
{
struct bcm2835_i2c_dev * i2c_dev ;
2014-02-11 22:02:36 +09:00
struct resource * mem , * irq ;
2013-02-11 19:47:56 -07:00
int ret ;
struct i2c_adapter * adap ;
2019-06-08 10:14:43 -07:00
struct clk * bus_clk ;
2019-06-21 03:52:50 -07:00
struct clk * mclk ;
2019-06-08 10:14:43 -07:00
u32 bus_clk_rate ;
2013-02-11 19:47:56 -07:00
i2c_dev = devm_kzalloc ( & pdev - > dev , sizeof ( * i2c_dev ) , GFP_KERNEL ) ;
2014-05-13 10:51:58 +09:00
if ( ! i2c_dev )
2013-02-11 19:47:56 -07:00
return - ENOMEM ;
platform_set_drvdata ( pdev , i2c_dev ) ;
i2c_dev - > dev = & pdev - > dev ;
init_completion ( & i2c_dev - > completion ) ;
mem = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
2014-02-11 22:02:36 +09:00
i2c_dev - > regs = devm_ioremap_resource ( & pdev - > dev , mem ) ;
if ( IS_ERR ( i2c_dev - > regs ) )
return PTR_ERR ( i2c_dev - > regs ) ;
2013-02-11 19:47:56 -07:00
2019-06-21 03:52:50 -07:00
mclk = devm_clk_get ( & pdev - > dev , NULL ) ;
if ( IS_ERR ( mclk ) ) {
if ( PTR_ERR ( mclk ) ! = - EPROBE_DEFER )
dev_err ( & pdev - > dev , " Could not get clock \n " ) ;
return PTR_ERR ( mclk ) ;
}
2019-06-08 10:14:43 -07:00
2019-06-21 03:52:50 -07:00
bus_clk = bcm2835_i2c_register_div ( & pdev - > dev , mclk , i2c_dev ) ;
2019-06-08 10:14:43 -07:00
if ( IS_ERR ( bus_clk ) ) {
dev_err ( & pdev - > dev , " Could not register clock \n " ) ;
return PTR_ERR ( bus_clk ) ;
}
ret = of_property_read_u32 ( pdev - > dev . of_node , " clock-frequency " ,
& bus_clk_rate ) ;
if ( ret < 0 ) {
dev_warn ( & pdev - > dev ,
" Could not read clock-frequency property \n " ) ;
bus_clk_rate = 100000 ;
}
ret = clk_set_rate_exclusive ( bus_clk , bus_clk_rate ) ;
if ( ret < 0 ) {
dev_err ( & pdev - > dev , " Could not set clock frequency \n " ) ;
return ret ;
}
ret = clk_prepare_enable ( bus_clk ) ;
if ( ret ) {
dev_err ( & pdev - > dev , " Couldn't prepare clock " ) ;
return ret ;
}
2019-06-21 03:52:49 -07:00
irq = platform_get_resource ( pdev , IORESOURCE_IRQ , 0 ) ;
if ( ! irq ) {
dev_err ( & pdev - > dev , " No IRQ resource \n " ) ;
return - ENODEV ;
}
i2c_dev - > irq = irq - > start ;
ret = request_irq ( i2c_dev - > irq , bcm2835_i2c_isr , IRQF_SHARED ,
dev_name ( & pdev - > dev ) , i2c_dev ) ;
if ( ret ) {
dev_err ( & pdev - > dev , " Could not request IRQ \n " ) ;
return - ENODEV ;
}
2013-02-11 19:47:56 -07:00
adap = & i2c_dev - > adapter ;
i2c_set_adapdata ( adap , i2c_dev ) ;
adap - > owner = THIS_MODULE ;
2014-07-10 13:46:23 +02:00
adap - > class = I2C_CLASS_DEPRECATED ;
2013-02-11 19:47:56 -07:00
strlcpy ( adap - > name , " bcm2835 I2C adapter " , sizeof ( adap - > name ) ) ;
adap - > algo = & bcm2835_i2c_algo ;
adap - > dev . parent = & pdev - > dev ;
2013-11-25 09:01:50 +01:00
adap - > dev . of_node = pdev - > dev . of_node ;
2015-10-29 12:34:25 +01:00
adap - > quirks = & bcm2835_i2c_quirks ;
2013-02-11 19:47:56 -07:00
bcm2835_i2c_writel ( i2c_dev , BCM2835_I2C_C , 0 ) ;
ret = i2c_add_adapter ( adap ) ;
if ( ret )
free_irq ( i2c_dev - > irq , i2c_dev ) ;
return ret ;
}
static int bcm2835_i2c_remove ( struct platform_device * pdev )
{
struct bcm2835_i2c_dev * i2c_dev = platform_get_drvdata ( pdev ) ;
2019-06-08 10:14:43 -07:00
struct clk * bus_clk = devm_clk_get ( i2c_dev - > dev , " div " ) ;
clk_rate_exclusive_put ( bus_clk ) ;
clk_disable_unprepare ( bus_clk ) ;
2013-02-11 19:47:56 -07:00
free_irq ( i2c_dev - > irq , i2c_dev ) ;
i2c_del_adapter ( & i2c_dev - > adapter ) ;
return 0 ;
}
static const struct of_device_id bcm2835_i2c_of_match [ ] = {
{ . compatible = " brcm,bcm2835-i2c " } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , bcm2835_i2c_of_match ) ;
static struct platform_driver bcm2835_i2c_driver = {
. probe = bcm2835_i2c_probe ,
. remove = bcm2835_i2c_remove ,
. driver = {
. name = " i2c-bcm2835 " ,
. of_match_table = bcm2835_i2c_of_match ,
} ,
} ;
module_platform_driver ( bcm2835_i2c_driver ) ;
MODULE_AUTHOR ( " Stephen Warren <swarren@wwwdotorg.org> " ) ;
MODULE_DESCRIPTION ( " BCM2835 I2C bus adapter " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;
MODULE_ALIAS ( " platform:i2c-bcm2835 " ) ;