Revision 2c1d9ecb hw/omap2.c
b/hw/omap2.c | ||
---|---|---|
795 | 795 |
} |
796 | 796 |
|
797 | 797 |
/* L4 Interconnect */ |
798 |
struct omap_target_agent_s { |
|
799 |
struct omap_l4_s *bus; |
|
800 |
int regions; |
|
801 |
struct omap_l4_region_s *start; |
|
802 |
target_phys_addr_t base; |
|
803 |
uint32_t component; |
|
804 |
uint32_t control; |
|
805 |
uint32_t status; |
|
806 |
}; |
|
807 |
|
|
808 |
struct omap_l4_s { |
|
809 |
target_phys_addr_t base; |
|
810 |
int ta_num; |
|
811 |
struct omap_target_agent_s ta[0]; |
|
812 |
}; |
|
813 |
|
|
814 |
#ifdef L4_MUX_HACK |
|
815 |
static int omap_l4_io_entries; |
|
816 |
static int omap_cpu_io_entry; |
|
817 |
static struct omap_l4_entry { |
|
818 |
CPUReadMemoryFunc * const *mem_read; |
|
819 |
CPUWriteMemoryFunc * const *mem_write; |
|
820 |
void *opaque; |
|
821 |
} *omap_l4_io_entry; |
|
822 |
static CPUReadMemoryFunc * const *omap_l4_io_readb_fn; |
|
823 |
static CPUReadMemoryFunc * const *omap_l4_io_readh_fn; |
|
824 |
static CPUReadMemoryFunc * const *omap_l4_io_readw_fn; |
|
825 |
static CPUWriteMemoryFunc * const *omap_l4_io_writeb_fn; |
|
826 |
static CPUWriteMemoryFunc * const *omap_l4_io_writeh_fn; |
|
827 |
static CPUWriteMemoryFunc * const *omap_l4_io_writew_fn; |
|
828 |
static void **omap_l4_io_opaque; |
|
829 |
|
|
830 |
int l4_register_io_memory(CPUReadMemoryFunc * const *mem_read, |
|
831 |
CPUWriteMemoryFunc * const *mem_write, void *opaque) |
|
832 |
{ |
|
833 |
omap_l4_io_entry[omap_l4_io_entries].mem_read = mem_read; |
|
834 |
omap_l4_io_entry[omap_l4_io_entries].mem_write = mem_write; |
|
835 |
omap_l4_io_entry[omap_l4_io_entries].opaque = opaque; |
|
836 |
|
|
837 |
return omap_l4_io_entries ++; |
|
838 |
} |
|
839 |
|
|
840 |
static uint32_t omap_l4_io_readb(void *opaque, target_phys_addr_t addr) |
|
841 |
{ |
|
842 |
unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS; |
|
843 |
|
|
844 |
return omap_l4_io_readb_fn[i](omap_l4_io_opaque[i], addr); |
|
845 |
} |
|
846 |
|
|
847 |
static uint32_t omap_l4_io_readh(void *opaque, target_phys_addr_t addr) |
|
848 |
{ |
|
849 |
unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS; |
|
850 |
|
|
851 |
return omap_l4_io_readh_fn[i](omap_l4_io_opaque[i], addr); |
|
852 |
} |
|
853 |
|
|
854 |
static uint32_t omap_l4_io_readw(void *opaque, target_phys_addr_t addr) |
|
855 |
{ |
|
856 |
unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS; |
|
857 |
|
|
858 |
return omap_l4_io_readw_fn[i](omap_l4_io_opaque[i], addr); |
|
859 |
} |
|
860 |
|
|
861 |
static void omap_l4_io_writeb(void *opaque, target_phys_addr_t addr, |
|
862 |
uint32_t value) |
|
863 |
{ |
|
864 |
unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS; |
|
865 |
|
|
866 |
return omap_l4_io_writeb_fn[i](omap_l4_io_opaque[i], addr, value); |
|
867 |
} |
|
868 |
|
|
869 |
static void omap_l4_io_writeh(void *opaque, target_phys_addr_t addr, |
|
870 |
uint32_t value) |
|
871 |
{ |
|
872 |
unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS; |
|
873 |
|
|
874 |
return omap_l4_io_writeh_fn[i](omap_l4_io_opaque[i], addr, value); |
|
875 |
} |
|
876 |
|
|
877 |
static void omap_l4_io_writew(void *opaque, target_phys_addr_t addr, |
|
878 |
uint32_t value) |
|
879 |
{ |
|
880 |
unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS; |
|
881 |
|
|
882 |
return omap_l4_io_writew_fn[i](omap_l4_io_opaque[i], addr, value); |
|
883 |
} |
|
884 |
|
|
885 |
static CPUReadMemoryFunc * const omap_l4_io_readfn[] = { |
|
886 |
omap_l4_io_readb, |
|
887 |
omap_l4_io_readh, |
|
888 |
omap_l4_io_readw, |
|
889 |
}; |
|
890 |
|
|
891 |
static CPUWriteMemoryFunc * const omap_l4_io_writefn[] = { |
|
892 |
omap_l4_io_writeb, |
|
893 |
omap_l4_io_writeh, |
|
894 |
omap_l4_io_writew, |
|
895 |
}; |
|
896 |
#endif |
|
897 |
|
|
898 |
struct omap_l4_s *omap_l4_init(target_phys_addr_t base, int ta_num) |
|
899 |
{ |
|
900 |
struct omap_l4_s *bus = qemu_mallocz( |
|
901 |
sizeof(*bus) + ta_num * sizeof(*bus->ta)); |
|
902 |
|
|
903 |
bus->ta_num = ta_num; |
|
904 |
bus->base = base; |
|
905 |
|
|
906 |
#ifdef L4_MUX_HACK |
|
907 |
omap_l4_io_entries = 1; |
|
908 |
omap_l4_io_entry = qemu_mallocz(125 * sizeof(*omap_l4_io_entry)); |
|
909 |
|
|
910 |
omap_cpu_io_entry = |
|
911 |
cpu_register_io_memory(omap_l4_io_readfn, |
|
912 |
omap_l4_io_writefn, bus); |
|
913 |
# define L4_PAGES (0xb4000 / TARGET_PAGE_SIZE) |
|
914 |
omap_l4_io_readb_fn = qemu_mallocz(sizeof(void *) * L4_PAGES); |
|
915 |
omap_l4_io_readh_fn = qemu_mallocz(sizeof(void *) * L4_PAGES); |
|
916 |
omap_l4_io_readw_fn = qemu_mallocz(sizeof(void *) * L4_PAGES); |
|
917 |
omap_l4_io_writeb_fn = qemu_mallocz(sizeof(void *) * L4_PAGES); |
|
918 |
omap_l4_io_writeh_fn = qemu_mallocz(sizeof(void *) * L4_PAGES); |
|
919 |
omap_l4_io_writew_fn = qemu_mallocz(sizeof(void *) * L4_PAGES); |
|
920 |
omap_l4_io_opaque = qemu_mallocz(sizeof(void *) * L4_PAGES); |
|
921 |
#endif |
|
922 |
|
|
923 |
return bus; |
|
924 |
} |
|
925 |
|
|
926 |
static uint32_t omap_l4ta_read(void *opaque, target_phys_addr_t addr) |
|
927 |
{ |
|
928 |
struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque; |
|
929 |
|
|
930 |
switch (addr) { |
|
931 |
case 0x00: /* COMPONENT */ |
|
932 |
return s->component; |
|
933 |
|
|
934 |
case 0x20: /* AGENT_CONTROL */ |
|
935 |
return s->control; |
|
936 |
|
|
937 |
case 0x28: /* AGENT_STATUS */ |
|
938 |
return s->status; |
|
939 |
} |
|
940 |
|
|
941 |
OMAP_BAD_REG(addr); |
|
942 |
return 0; |
|
943 |
} |
|
944 |
|
|
945 |
static void omap_l4ta_write(void *opaque, target_phys_addr_t addr, |
|
946 |
uint32_t value) |
|
947 |
{ |
|
948 |
struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque; |
|
949 |
|
|
950 |
switch (addr) { |
|
951 |
case 0x00: /* COMPONENT */ |
|
952 |
case 0x28: /* AGENT_STATUS */ |
|
953 |
OMAP_RO_REG(addr); |
|
954 |
break; |
|
955 |
|
|
956 |
case 0x20: /* AGENT_CONTROL */ |
|
957 |
s->control = value & 0x01000700; |
|
958 |
if (value & 1) /* OCP_RESET */ |
|
959 |
s->status &= ~1; /* REQ_TIMEOUT */ |
|
960 |
break; |
|
961 |
|
|
962 |
default: |
|
963 |
OMAP_BAD_REG(addr); |
|
964 |
} |
|
965 |
} |
|
966 |
|
|
967 |
static CPUReadMemoryFunc * const omap_l4ta_readfn[] = { |
|
968 |
omap_badwidth_read16, |
|
969 |
omap_l4ta_read, |
|
970 |
omap_badwidth_read16, |
|
971 |
}; |
|
972 |
|
|
973 |
static CPUWriteMemoryFunc * const omap_l4ta_writefn[] = { |
|
974 |
omap_badwidth_write32, |
|
975 |
omap_badwidth_write32, |
|
976 |
omap_l4ta_write, |
|
977 |
}; |
|
978 |
|
|
979 | 798 |
#define L4TA(n) (n) |
980 | 799 |
#define L4TAO(n) ((n) + 39) |
981 | 800 |
|
982 |
static struct omap_l4_region_s { |
|
983 |
target_phys_addr_t offset; |
|
984 |
size_t size; |
|
985 |
int access; |
|
986 |
} omap_l4_region[125] = { |
|
801 |
static const struct omap_l4_region_s omap_l4_region[125] = { |
|
987 | 802 |
[ 1] = { 0x40800, 0x800, 32 }, /* Initiator agent */ |
988 | 803 |
[ 2] = { 0x41000, 0x1000, 32 }, /* Link agent */ |
989 | 804 |
[ 0] = { 0x40000, 0x800, 32 }, /* Address and protection */ |
... | ... | |
1111 | 926 |
[124] = { 0xb3000, 0x1000, 32 | 16 | 8 }, /* L4TA39 */ |
1112 | 927 |
}; |
1113 | 928 |
|
1114 |
static struct omap_l4_agent_info_s { |
|
1115 |
int ta; |
|
1116 |
int region; |
|
1117 |
int regions; |
|
1118 |
int ta_region; |
|
1119 |
} omap_l4_agent_info[54] = { |
|
929 |
static const struct omap_l4_agent_info_s omap_l4_agent_info[54] = { |
|
1120 | 930 |
{ 0, 0, 3, 2 }, /* L4IA initiatior agent */ |
1121 | 931 |
{ L4TAO(1), 3, 2, 1 }, /* Control and pinout module */ |
1122 | 932 |
{ L4TAO(2), 5, 2, 1 }, /* 32K timer */ |
... | ... | |
1173 | 983 |
{ L4TA(39), 123, 2, 1 }, /* HDQ/1-Wire */ |
1174 | 984 |
}; |
1175 | 985 |
|
1176 |
#define omap_l4ta(bus, cs) omap_l4ta_get(bus, L4TA(cs)) |
|
1177 |
#define omap_l4tao(bus, cs) omap_l4ta_get(bus, L4TAO(cs)) |
|
1178 |
|
|
1179 |
struct omap_target_agent_s *omap_l4ta_get(struct omap_l4_s *bus, int cs) |
|
1180 |
{ |
|
1181 |
int i, iomemtype; |
|
1182 |
struct omap_target_agent_s *ta = NULL; |
|
1183 |
struct omap_l4_agent_info_s *info = NULL; |
|
1184 |
|
|
1185 |
for (i = 0; i < bus->ta_num; i ++) |
|
1186 |
if (omap_l4_agent_info[i].ta == cs) { |
|
1187 |
ta = &bus->ta[i]; |
|
1188 |
info = &omap_l4_agent_info[i]; |
|
1189 |
break; |
|
1190 |
} |
|
1191 |
if (!ta) { |
|
1192 |
fprintf(stderr, "%s: bad target agent (%i)\n", __FUNCTION__, cs); |
|
1193 |
exit(-1); |
|
1194 |
} |
|
1195 |
|
|
1196 |
ta->bus = bus; |
|
1197 |
ta->start = &omap_l4_region[info->region]; |
|
1198 |
ta->regions = info->regions; |
|
1199 |
|
|
1200 |
ta->component = ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0); |
|
1201 |
ta->status = 0x00000000; |
|
1202 |
ta->control = 0x00000200; /* XXX 01000200 for L4TAO */ |
|
1203 |
|
|
1204 |
iomemtype = l4_register_io_memory(omap_l4ta_readfn, |
|
1205 |
omap_l4ta_writefn, ta); |
|
1206 |
ta->base = omap_l4_attach(ta, info->ta_region, iomemtype); |
|
1207 |
|
|
1208 |
return ta; |
|
1209 |
} |
|
1210 |
|
|
1211 |
target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, int region, |
|
1212 |
int iotype) |
|
1213 |
{ |
|
1214 |
target_phys_addr_t base; |
|
1215 |
ssize_t size; |
|
1216 |
#ifdef L4_MUX_HACK |
|
1217 |
int i; |
|
1218 |
#endif |
|
1219 |
|
|
1220 |
if (region < 0 || region >= ta->regions) { |
|
1221 |
fprintf(stderr, "%s: bad io region (%i)\n", __FUNCTION__, region); |
|
1222 |
exit(-1); |
|
1223 |
} |
|
1224 |
|
|
1225 |
base = ta->bus->base + ta->start[region].offset; |
|
1226 |
size = ta->start[region].size; |
|
1227 |
if (iotype) { |
|
1228 |
#ifndef L4_MUX_HACK |
|
1229 |
cpu_register_physical_memory(base, size, iotype); |
|
1230 |
#else |
|
1231 |
cpu_register_physical_memory(base, size, omap_cpu_io_entry); |
|
1232 |
i = (base - ta->bus->base) / TARGET_PAGE_SIZE; |
|
1233 |
for (; size > 0; size -= TARGET_PAGE_SIZE, i ++) { |
|
1234 |
omap_l4_io_readb_fn[i] = omap_l4_io_entry[iotype].mem_read[0]; |
|
1235 |
omap_l4_io_readh_fn[i] = omap_l4_io_entry[iotype].mem_read[1]; |
|
1236 |
omap_l4_io_readw_fn[i] = omap_l4_io_entry[iotype].mem_read[2]; |
|
1237 |
omap_l4_io_writeb_fn[i] = omap_l4_io_entry[iotype].mem_write[0]; |
|
1238 |
omap_l4_io_writeh_fn[i] = omap_l4_io_entry[iotype].mem_write[1]; |
|
1239 |
omap_l4_io_writew_fn[i] = omap_l4_io_entry[iotype].mem_write[2]; |
|
1240 |
omap_l4_io_opaque[i] = omap_l4_io_entry[iotype].opaque; |
|
1241 |
} |
|
1242 |
#endif |
|
1243 |
} |
|
1244 |
|
|
1245 |
return base; |
|
1246 |
} |
|
986 |
#define omap_l4ta(bus, cs) \ |
|
987 |
omap_l4ta_get(bus, omap_l4_region, omap_l4_agent_info, L4TA(cs)) |
|
988 |
#define omap_l4tao(bus, cs) \ |
|
989 |
omap_l4ta_get(bus, omap_l4_region, omap_l4_agent_info, L4TAO(cs)) |
|
1247 | 990 |
|
1248 | 991 |
/* Power, Reset, and Clock Management */ |
1249 | 992 |
struct omap_prcm_s { |
Also available in: Unified diff