]> git.sur5r.net Git - u-boot/blob - cpu/at32ap/device.c
Add AT32AP CPU and AT32AP7000 SoC support
[u-boot] / cpu / at32ap / device.c
1 /*
2  * Copyright (C) 2006 Atmel Corporation
3  *
4  * See file CREDITS for list of people who contributed to this
5  * project.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2 of
10  * the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20  * MA 02111-1307 USA
21  */
22 #include <common.h>
23
24 #include <asm/arch/platform.h>
25
26 #include "sm.h"
27
28 struct device_state {
29         int refcount;
30 };
31
32 static struct device_state device_state[NR_DEVICES];
33
34 static int claim_resource(const struct resource *res)
35 {
36         int ret = 0;
37
38         switch (res->type) {
39         case RESOURCE_GPIO:
40                 ret = gpio_set_func(res->u.gpio.gpio_dev,
41                                     res->u.gpio.start,
42                                     res->u.gpio.nr_pins,
43                                     res->u.gpio.func);
44                 break;
45         case RESOURCE_CLOCK:
46                 ret = pm_enable_clock(res->u.clock.id, res->u.clock.index);
47                 break;
48         }
49
50         return ret;
51 }
52
53 static void free_resource(const struct resource *res)
54 {
55         switch (res->type) {
56         case RESOURCE_GPIO:
57                 gpio_free(res->u.gpio.gpio_dev, res->u.gpio.start,
58                           res->u.gpio.nr_pins);
59                 break;
60         case RESOURCE_CLOCK:
61                 pm_disable_clock(res->u.clock.id, res->u.clock.index);
62                 break;
63         }
64 }
65
66 static int init_dev(const struct device *dev)
67 {
68         unsigned int i;
69         int ret = 0;
70
71         for (i = 0; i < dev->nr_resources; i++) {
72                 ret = claim_resource(&dev->resource[i]);
73                 if (ret)
74                         goto cleanup;
75         }
76
77         return 0;
78
79 cleanup:
80         while (i--)
81                 free_resource(&dev->resource[i]);
82
83         return ret;
84 }
85
86 const struct device *get_device(enum device_id devid)
87 {
88         struct device_state *devstate;
89         const struct device *dev;
90         unsigned long flags;
91         int initialized = 0;
92         int ret = 0;
93
94         devstate = &device_state[devid];
95         dev = &chip_device[devid];
96
97         flags = disable_interrupts();
98         if (devstate->refcount++)
99                 initialized = 1;
100         if (flags)
101                 enable_interrupts();
102
103         if (!initialized)
104                 ret = init_dev(dev);
105
106         return ret ? NULL : dev;
107 }
108
109 void put_device(const struct device *dev)
110 {
111         struct device_state *devstate;
112         unsigned long devid, flags;
113
114         devid = (unsigned long)(dev - chip_device) / sizeof(struct device);
115         devstate = &device_state[devid];
116
117         flags = disable_interrupts();
118         devstate--;
119         if (!devstate) {
120                 unsigned int i;
121                 for (i = 0; i < dev->nr_resources; i++)
122                         free_resource(&dev->resource[i]);
123         }
124         if (flags)
125                 enable_interrupts();
126 }