Setting up repository
[linux-libre-firmware.git] / carl9170fw / carlfw / src / cam.c
1 /*
2  * carl9170 firmware - used by the ar9170 wireless device
3  *
4  * Security Engine
5  *
6  * Copyright (c) 2000-2005 ZyDAS Technology Corporation
7  * Copyright (c) 2007-2009 Atheros Communications, Inc.
8  * Copyright    2009    Johannes Berg <johannes@sipsolutions.net>
9  * Copyright 2009-2011  Christian Lamparter <chunkeey@googlemail.com>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License along
22  * with this program; if not, write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  */
25
26 #include "carl9170.h"
27 #include "cam.h"
28
29 #ifdef CONFIG_CARL9170FW_SECURITY_ENGINE
30 static void disable_cam_user(const uint16_t userId)
31 {
32         if (userId <= 31)
33                 andl(AR9170_MAC_REG_CAM_ROLL_CALL_TBL_L, (~((uint32_t) 1 << userId)));
34         else if (userId <= 63)
35                 andl(AR9170_MAC_REG_CAM_ROLL_CALL_TBL_H, (~((uint32_t) 1 << (userId - 32))));
36 }
37
38 static void enable_cam_user(const uint16_t userId)
39 {
40         if (userId <= 31)
41                 orl(AR9170_MAC_REG_CAM_ROLL_CALL_TBL_L, (((uint32_t) 1) << userId));
42         else if (userId <= 63)
43                 orl(AR9170_MAC_REG_CAM_ROLL_CALL_TBL_H, (((uint32_t) 1) << (userId - 32)));
44 }
45
46 static void wait_for_cam_read_ready(void)
47 {
48         while ((get(AR9170_MAC_REG_CAM_STATE) & AR9170_MAC_CAM_STATE_READ_PENDING) == 0) {
49                 /*
50                  * wait
51                  */
52         }
53 }
54
55 static void wait_for_cam_write_ready(void)
56 {
57         while ((get(AR9170_MAC_REG_CAM_STATE) & AR9170_MAC_CAM_STATE_WRITE_PENDING) == 0) {
58                 /*
59                  * wait some more
60                  */
61         }
62 }
63
64 static void HW_CAM_Avail(void)
65 {
66         uint32_t tmpValue;
67
68         do {
69                 tmpValue = get(AR9170_MAC_REG_CAM_MODE);
70         } while (tmpValue & AR9170_MAC_CAM_HOST_PENDING);
71 }
72
73 static void HW_CAM_Write128(const uint32_t address, const uint32_t *data)
74 {
75         HW_CAM_Avail();
76
77         set(AR9170_MAC_REG_CAM_DATA0, data[0]);
78         set(AR9170_MAC_REG_CAM_DATA1, data[1]);
79         set(AR9170_MAC_REG_CAM_DATA2, data[2]);
80         set(AR9170_MAC_REG_CAM_DATA3, data[3]);
81
82         set(AR9170_MAC_REG_CAM_ADDR, address | AR9170_MAC_CAM_ADDR_WRITE);
83
84         wait_for_cam_write_ready();
85 }
86
87 static void HW_CAM_Read128(const uint32_t address, uint32_t *data)
88 {
89
90         HW_CAM_Avail();
91         set(AR9170_MAC_REG_CAM_ADDR, address);
92
93         wait_for_cam_read_ready();
94         HW_CAM_Avail();
95         data[0] = get(AR9170_MAC_REG_CAM_DATA0);
96         data[1] = get(AR9170_MAC_REG_CAM_DATA1);
97         data[2] = get(AR9170_MAC_REG_CAM_DATA2);
98         data[3] = get(AR9170_MAC_REG_CAM_DATA3);
99 }
100
101 void set_key(const struct carl9170_set_key_cmd *key)
102 {
103         uint32_t data[4];
104         uint16_t row, wordId, nibbleId, i;
105
106         if (key->user > (AR9170_CAM_MAX_USER + 3))
107                 return ;
108
109         if (key->keyId > 1)
110                 return ;
111
112         /* Disable Key */
113         disable_cam_user(key->user);
114
115         /* Set encrypt type */
116         if (key->user >= AR9170_CAM_MAX_USER) {
117                 /* default */
118                 row = DEFAULT_ENCRY_TYPE;
119                 wordId = 0;
120                 nibbleId = (key->user - AR9170_CAM_MAX_USER) & 0x7;
121         } else {
122                 row = ENCRY_TYPE_START_ADDR + (key->user >> 5);
123                 wordId = (key->user >> 3) & 0x3;
124                 nibbleId = key->user & 0x7;
125         }
126
127         HW_CAM_Read128(row, data);
128         data[wordId] &= (~(0xf << ((uint32_t) nibbleId * 4)));
129         data[wordId] |= (key->type << ((uint32_t) nibbleId * 4));
130         HW_CAM_Write128(row, data);
131
132         /* Set MAC address */
133         if (key->user < AR9170_CAM_MAX_USER) {
134                 uint16_t byteId;
135                 wordId = (key->user >> 2) & 0x3;
136                 byteId = key->user & 0x3;
137                 row = (key->user >> 4) * 6;
138
139                 for (i = 0; i < 6; i++) {
140                         HW_CAM_Read128(row + i, data);
141                         data[wordId] &= (~(0xff << ((uint32_t) byteId * 8)));
142                         data[wordId] |= (key->macAddr[i] << ((uint32_t) byteId * 8));
143                         HW_CAM_Write128(row + i, data);
144                 }
145         }
146
147         /* Set key */
148         row = KEY_START_ADDR + (key->user * 2) + key->keyId;
149
150         HW_CAM_Write128(row, key->key);
151
152         /* Enable Key */
153         enable_cam_user(key->user);
154 }
155
156 void disable_key(const struct carl9170_disable_key_cmd *key)
157 {
158         disable_cam_user(key->user);
159 }
160
161 #endif /* CONFIG_CARL9170FW_SECURITY_ENGINE */