Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 295395
b: refs/heads/master
c: d9dc878
h: refs/heads/master
i:
  295393: ee7af76
  295391: 658ff29
v: v3
  • Loading branch information
Russell King committed Jan 26, 2012
1 parent 45726f8 commit 71dd668
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 4 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: e0d21178ceb06f5bfa81a5697f68384f74af054a
refs/heads/master: d9dc878769f521f494d1617d7cd0c92073df75d8
120 changes: 117 additions & 3 deletions trunk/drivers/pcmcia/soc_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@


#include <linux/cpufreq.h>
#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
Expand All @@ -49,6 +50,8 @@

#include "soc_common.h"

static irqreturn_t soc_common_pcmcia_interrupt(int irq, void *dev);

#ifdef CONFIG_PCMCIA_DEBUG

static int pc_debug;
Expand Down Expand Up @@ -104,13 +107,116 @@ void soc_common_pcmcia_get_timing(struct soc_pcmcia_socket *skt,
}
EXPORT_SYMBOL(soc_common_pcmcia_get_timing);

static void __soc_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt,
unsigned int nr)
{
unsigned int i;

for (i = 0; i < nr; i++) {
if (skt->stat[i].irq)
free_irq(skt->stat[i].irq, skt);
if (gpio_is_valid(skt->stat[i].gpio))
gpio_free(skt->stat[i].gpio);
}

if (skt->ops->hw_shutdown)
skt->ops->hw_shutdown(skt);
}

static void soc_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
{
__soc_pcmcia_hw_shutdown(skt, ARRAY_SIZE(skt->stat));
}

static int soc_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
{
int ret = 0, i;

if (skt->ops->hw_init) {
ret = skt->ops->hw_init(skt);
if (ret)
return ret;
}

for (i = 0; i < ARRAY_SIZE(skt->stat); i++) {
if (gpio_is_valid(skt->stat[i].gpio)) {
int irq;

ret = gpio_request_one(skt->stat[i].gpio, GPIOF_IN,
skt->stat[i].name);
if (ret) {
__soc_pcmcia_hw_shutdown(skt, i);
return ret;
}

irq = gpio_to_irq(skt->stat[i].gpio);

if (i == SOC_STAT_RDY)
skt->socket.pci_irq = irq;
else
skt->stat[i].irq = irq;
}

if (skt->stat[i].irq) {
ret = request_irq(skt->stat[i].irq,
soc_common_pcmcia_interrupt,
IRQF_TRIGGER_NONE,
skt->stat[i].name, skt);
if (ret) {
if (gpio_is_valid(skt->stat[i].gpio))
gpio_free(skt->stat[i].gpio);
__soc_pcmcia_hw_shutdown(skt, i);
return ret;
}
}
}

return ret;
}

static void soc_pcmcia_hw_enable(struct soc_pcmcia_socket *skt)
{
int i;

for (i = 0; i < ARRAY_SIZE(skt->stat); i++)
if (skt->stat[i].irq) {
irq_set_irq_type(skt->stat[i].irq, IRQ_TYPE_EDGE_RISING);
irq_set_irq_type(skt->stat[i].irq, IRQ_TYPE_EDGE_BOTH);
}
}

static void soc_pcmcia_hw_disable(struct soc_pcmcia_socket *skt)
{
int i;

for (i = 0; i < ARRAY_SIZE(skt->stat); i++)
if (skt->stat[i].irq)
irq_set_irq_type(skt->stat[i].irq, IRQ_TYPE_NONE);
}

static unsigned int soc_common_pcmcia_skt_state(struct soc_pcmcia_socket *skt)
{
struct pcmcia_state state;
unsigned int stat;

memset(&state, 0, sizeof(struct pcmcia_state));

/* Make battery voltage state report 'good' */
state.bvd1 = 1;
state.bvd2 = 1;

/* CD is active low by default */
if (gpio_is_valid(skt->stat[SOC_STAT_CD].gpio))
state.detect = !gpio_get_value(skt->stat[SOC_STAT_CD].gpio);

/* RDY and BVD are active high by default */
if (gpio_is_valid(skt->stat[SOC_STAT_RDY].gpio))
state.ready = !!gpio_get_value(skt->stat[SOC_STAT_RDY].gpio);
if (gpio_is_valid(skt->stat[SOC_STAT_BVD1].gpio))
state.bvd1 = !!gpio_get_value(skt->stat[SOC_STAT_BVD1].gpio);
if (gpio_is_valid(skt->stat[SOC_STAT_BVD2].gpio))
state.bvd2 = !!gpio_get_value(skt->stat[SOC_STAT_BVD2].gpio);

skt->ops->socket_state(skt, &state);

stat = state.detect ? SS_DETECT : 0;
Expand Down Expand Up @@ -188,6 +294,7 @@ static int soc_common_pcmcia_sock_init(struct pcmcia_socket *sock)
debug(skt, 2, "initializing socket\n");
if (skt->ops->socket_init)
skt->ops->socket_init(skt);
soc_pcmcia_hw_enable(skt);
return 0;
}

Expand All @@ -207,6 +314,7 @@ static int soc_common_pcmcia_suspend(struct pcmcia_socket *sock)

debug(skt, 2, "suspending socket\n");

soc_pcmcia_hw_disable(skt);
if (skt->ops->socket_suspend)
skt->ops->socket_suspend(skt);

Expand Down Expand Up @@ -638,10 +746,15 @@ module_exit(soc_pcmcia_cpufreq_unregister);
void soc_pcmcia_init_one(struct soc_pcmcia_socket *skt,
struct pcmcia_low_level *ops, struct device *dev)
{
int i;

skt->ops = ops;
skt->socket.owner = ops->owner;
skt->socket.dev.parent = dev;
skt->socket.pci_irq = NO_IRQ;

for (i = 0; i < ARRAY_SIZE(skt->stat); i++)
skt->stat[i].gpio = -EINVAL;
}
EXPORT_SYMBOL(soc_pcmcia_init_one);

Expand All @@ -652,8 +765,9 @@ void soc_pcmcia_remove_one(struct soc_pcmcia_socket *skt)

pcmcia_unregister_socket(&skt->socket);

skt->ops->hw_shutdown(skt);
soc_pcmcia_hw_shutdown(skt);

/* should not be required; violates some lowlevel drivers */
soc_common_pcmcia_config_skt(skt, &dead_socket);

list_del(&skt->node);
Expand Down Expand Up @@ -710,7 +824,7 @@ int soc_pcmcia_add_one(struct soc_pcmcia_socket *skt)
*/
skt->ops->set_timing(skt);

ret = skt->ops->hw_init(skt);
ret = soc_pcmcia_hw_init(skt);
if (ret)
goto out_err_6;

Expand Down Expand Up @@ -743,7 +857,7 @@ int soc_pcmcia_add_one(struct soc_pcmcia_socket *skt)
pcmcia_unregister_socket(&skt->socket);

out_err_7:
skt->ops->hw_shutdown(skt);
soc_pcmcia_hw_shutdown(skt);
out_err_6:
list_del(&skt->node);
mutex_unlock(&soc_pcmcia_sockets_lock);
Expand Down
10 changes: 10 additions & 0 deletions trunk/drivers/pcmcia/soc_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,16 @@ struct soc_pcmcia_socket {
struct resource res_attr;
void __iomem *virt_io;

struct {
int gpio;
unsigned int irq;
const char *name;
} stat[4];
#define SOC_STAT_CD 0 /* Card detect */
#define SOC_STAT_BVD1 1 /* BATDEAD / IOSTSCHG */
#define SOC_STAT_BVD2 2 /* BATWARN / IOSPKR */
#define SOC_STAT_RDY 3 /* Ready / Interrupt */

unsigned int irq_state;

struct timer_list poll_timer;
Expand Down

0 comments on commit 71dd668

Please sign in to comment.